/***
 * ASM: a very small and fast Java bytecode manipulation framework
 * Copyright (c) 2000-2011 INRIA, France Telecom
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the copyright holders nor the names of its
 *    contributors may be used to endorse or promote products derived from
 *    this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.nutz.repo.org.objectweb.asm;

/**
 * An {@link FieldVisitor} that generates Java fields in bytecode form.
 *
 * @author Eric Bruneton
 */
final class FieldWriter extends FieldVisitor {

    /**
     * The class writer to which this field must be added.
     */
    private final ClassWriter cw;

    /**
     * Access flags of this field.
     */
    private final int access;

    /**
     * The index of the constant pool item that contains the name of this
     * method.
     */
    private final int name;

    /**
     * The index of the constant pool item that contains the descriptor of this
     * field.
     */
    private final int desc;

    /**
     * The index of the constant pool item that contains the signature of this
     * field.
     */
    private int signature;

    /**
     * The index of the constant pool item that contains the constant value of
     * this field.
     */
    private int value;

    /**
     * The runtime visible annotations of this field. May be <tt>null</tt>.
     */
    private AnnotationWriter anns;

    /**
     * The runtime invisible annotations of this field. May be <tt>null</tt>.
     */
    private AnnotationWriter ianns;

    /**
     * The runtime visible type annotations of this field. May be <tt>null</tt>.
     */
    private AnnotationWriter tanns;

    /**
     * The runtime invisible type annotations of this field. May be
     * <tt>null</tt>.
     */
    private AnnotationWriter itanns;

    /**
     * The non standard attributes of this field. May be <tt>null</tt>.
     */
    private Attribute attrs;

    // ------------------------------------------------------------------------
    // Constructor
    // ------------------------------------------------------------------------

    /**
     * Constructs a new {@link FieldWriter}.
     *
     * @param cw
     *            the class writer to which this field must be added.
     * @param access
     *            the field's access flags (see {@link Opcodes}).
     * @param name
     *            the field's name.
     * @param desc
     *            the field's descriptor (see {@link Type}).
     * @param signature
     *            the field's signature. May be <tt>null</tt>.
     * @param value
     *            the field's constant value. May be <tt>null</tt>.
     */
    FieldWriter(final ClassWriter cw, final int access, final String name,
            final String desc, final String signature, final Object value) {
        super(Opcodes.ASM5);
        if (cw.firstField == null) {
            cw.firstField = this;
        } else {
            cw.lastField.fv = this;
        }
        cw.lastField = this;
        this.cw = cw;
        this.access = access;
        this.name = cw.newUTF8(name);
        this.desc = cw.newUTF8(desc);
        if (ClassReader.SIGNATURES && signature != null) {
            this.signature = cw.newUTF8(signature);
        }
        if (value != null) {
            this.value = cw.newConstItem(value).index;
        }
    }

    // ------------------------------------------------------------------------
    // Implementation of the FieldVisitor abstract class
    // ------------------------------------------------------------------------

    @Override
    public AnnotationVisitor visitAnnotation(final String desc,
            final boolean visible) {
        if (!ClassReader.ANNOTATIONS) {
            return null;
        }
        ByteVector bv = new ByteVector();
        // write type, and reserve space for values count
        bv.putShort(cw.newUTF8(desc)).putShort(0);
        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
        if (visible) {
            aw.next = anns;
            anns = aw;
        } else {
            aw.next = ianns;
            ianns = aw;
        }
        return aw;
    }

    @Override
    public AnnotationVisitor visitTypeAnnotation(final int typeRef,
            final TypePath typePath, final String desc, final boolean visible) {
        if (!ClassReader.ANNOTATIONS) {
            return null;
        }
        ByteVector bv = new ByteVector();
        // write target_type and target_info
        AnnotationWriter.putTarget(typeRef, typePath, bv);
        // write type, and reserve space for values count
        bv.putShort(cw.newUTF8(desc)).putShort(0);
        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
                bv.length - 2);
        if (visible) {
            aw.next = tanns;
            tanns = aw;
        } else {
            aw.next = itanns;
            itanns = aw;
        }
        return aw;
    }

    @Override
    public void visitAttribute(final Attribute attr) {
        attr.next = attrs;
        attrs = attr;
    }

    @Override
    public void visitEnd() {
    }

    // ------------------------------------------------------------------------
    // Utility methods
    // ------------------------------------------------------------------------

    /**
     * Returns the size of this field.
     *
     * @return the size of this field.
     */
    int getSize() {
        int size = 8;
        if (value != 0) {
            cw.newUTF8("ConstantValue");
            size += 8;
        }
        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
            if ((cw.version & 0xFFFF) < Opcodes.V1_5
                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
                cw.newUTF8("Synthetic");
                size += 6;
            }
        }
        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
            cw.newUTF8("Deprecated");
            size += 6;
        }
        if (ClassReader.SIGNATURES && signature != 0) {
            cw.newUTF8("Signature");
            size += 8;
        }
        if (ClassReader.ANNOTATIONS && anns != null) {
            cw.newUTF8("RuntimeVisibleAnnotations");
            size += 8 + anns.getSize();
        }
        if (ClassReader.ANNOTATIONS && ianns != null) {
            cw.newUTF8("RuntimeInvisibleAnnotations");
            size += 8 + ianns.getSize();
        }
        if (ClassReader.ANNOTATIONS && tanns != null) {
            cw.newUTF8("RuntimeVisibleTypeAnnotations");
            size += 8 + tanns.getSize();
        }
        if (ClassReader.ANNOTATIONS && itanns != null) {
            cw.newUTF8("RuntimeInvisibleTypeAnnotations");
            size += 8 + itanns.getSize();
        }
        if (attrs != null) {
            size += attrs.getSize(cw, null, 0, -1, -1);
        }
        return size;
    }

    /**
     * Puts the content of this field into the given byte vector.
     *
     * @param out
     *            where the content of this field must be put.
     */
    void put(final ByteVector out) {
        final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
        int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
                | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
        out.putShort(access & ~mask).putShort(name).putShort(desc);
        int attributeCount = 0;
        if (value != 0) {
            ++attributeCount;
        }
        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
            if ((cw.version & 0xFFFF) < Opcodes.V1_5
                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
                ++attributeCount;
            }
        }
        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
            ++attributeCount;
        }
        if (ClassReader.SIGNATURES && signature != 0) {
            ++attributeCount;
        }
        if (ClassReader.ANNOTATIONS && anns != null) {
            ++attributeCount;
        }
        if (ClassReader.ANNOTATIONS && ianns != null) {
            ++attributeCount;
        }
        if (ClassReader.ANNOTATIONS && tanns != null) {
            ++attributeCount;
        }
        if (ClassReader.ANNOTATIONS && itanns != null) {
            ++attributeCount;
        }
        if (attrs != null) {
            attributeCount += attrs.getCount();
        }
        out.putShort(attributeCount);
        if (value != 0) {
            out.putShort(cw.newUTF8("ConstantValue"));
            out.putInt(2).putShort(value);
        }
        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
            if ((cw.version & 0xFFFF) < Opcodes.V1_5
                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
                out.putShort(cw.newUTF8("Synthetic")).putInt(0);
            }
        }
        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
            out.putShort(cw.newUTF8("Deprecated")).putInt(0);
        }
        if (ClassReader.SIGNATURES && signature != 0) {
            out.putShort(cw.newUTF8("Signature"));
            out.putInt(2).putShort(signature);
        }
        if (ClassReader.ANNOTATIONS && anns != null) {
            out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
            anns.put(out);
        }
        if (ClassReader.ANNOTATIONS && ianns != null) {
            out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
            ianns.put(out);
        }
        if (ClassReader.ANNOTATIONS && tanns != null) {
            out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
            tanns.put(out);
        }
        if (ClassReader.ANNOTATIONS && itanns != null) {
            out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
            itanns.put(out);
        }
        if (attrs != null) {
            attrs.put(cw, null, 0, -1, -1, out);
        }
    }
}


package org.nutz.json;

import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import java.util.regex.Pattern;

import org.nutz.castor.Castors;
import org.nutz.lang.util.NutMap;

/**
 * 描述Json输出的格式
 *
 * @author zozoh(zozohtnt@gmail.com)
 * @author Wendal(wendal1985@gmail.com)
 * @author 有心猴(belialofking@163.com)
 *
 */
public class JsonFormat extends NutMap {

    private static final long serialVersionUID = 1L;
    private static char DEFAULT_SEPARATOR = '\"';

    /**
     * 紧凑模式 -- 无换行,忽略null值
     */
    public static JsonFormat compact() {
        return new JsonFormat(true).setIgnoreNull(true);
    }

    /**
     * 全部输出模式 -- 换行,不忽略null值
     */
    public static JsonFormat full() {
        return new JsonFormat(false).setIgnoreNull(false);
    }

    /**
     * 一般模式 -- 换行,但忽略null值
     */
    public static JsonFormat nice() {
        return new JsonFormat(false).setIgnoreNull(true);
    }

    /**
     * 为了打印出来容易看，把名字去掉引号
     */
    public static JsonFormat forLook() {
        return new JsonFormat(false).setQuoteName(false).setIgnoreNull(true);
    }

    /**
     * 不换行,不忽略空值
     */
    public static JsonFormat tidy() {
        return new JsonFormat(true).setIgnoreNull(false);
    }

    /**
     * 获得一个Json输出格式，默认格式如下:

     *
使用紧凑模式输出
     *
缩进时用的字符串为『   』（三个空格）
     *
给字段添加双引号
     *
分隔符为『"』
     *
     */
    public JsonFormat() {
        this(true);
    }

    /**
     * 获得一个Json输出格式，默认格式如下:

     *
缩进时用的字符串为『   』（三个空格）
     *
给字段添加双引号
     *
分隔符为『"』
     *
     * @param compact
     *            true: 使用紧凑模式输出，false: 不使用紧凑模式输出
     */
    public JsonFormat(boolean compact) {
        setCompact(compact);
    }

    public static class Function {
    	/**
    	 * 是否忽略 JsonShape 注解
    	 */
    	public static String ignoreJsonShape = "ignoreJsonShape";
        /**
         * 缩进时用的字符串
         */
        public static String indentBy = "indentBy";
        /**
         * 是否使用紧凑模式输出
         */
        public static String compact = "compact";
        /**
         * 是否给字段添加双引号
         */
        public static String quoteName = "quoteName";
        /**
         * 是否忽略null值
         */
        public static String ignoreNull = "ignoreNull";
        /**
         * 仅输出的字段的正则表达式
         */
        public static String actived = "actived";
        /**
         * 不输出的字段的正则表达式
         */
        public static String locked = "locked";
        /**
         * 用到的类型转换器
         */
        public static String castors = "castors";
        /**
         * 分隔符
         */
        public static String separator = "separator";
        /**
         * 是否自动将值应用Unicode编码
         */
        public static String autoUnicode = "autoUnicode";
        /**
         * unicode编码用大写还是小写
         */
        public static String unicodeLower = "unicodeLower";
        /**
         * 日期格式
         */
        public static String dateFormat = "dateFormat";
        /**
         * 数字格式
         */
        public static String numberFormat = "numberFormat";
        /**
         * 遇到空值的时候写入字符串
         */
        public static String nullAsEmtry = "nullAsEmtry";
        public static String nullListAsEmpty = "nullListAsEmpty";
        public static String nullStringAsEmpty = "nullStringAsEmpty";
        public static String nullBooleanAsFalse = "nullBooleanAsFalse";
        public static String nullNumberAsZero = "nullNumberAsZero";
        public static String timeZone = "timeZone";
        public static String locale = "locale";
        public static String dateFormatRaw = "dateFormatRaw";
    }

    @JsonField(ignore = true)
    private Castors castors;

    /**
     * 判断该字段是否是指定输出方式中的字段
     *
     * @param name
     *            字段名
     * @return true: 该字段在忽略字段中，false: 该字段不在忽略字段中
     */
    public boolean ignore(String name) {
        if (null != getActived())
            return !getActived().matcher(name).find();
        if (null != getLocked())
            return getLocked().matcher(name).find();
        return false;
    }

    // ===================================================================
    // getter setter

    /**
     * Json输出格式的紧凑模式
     *
     * @return true: 使用紧凑模式输出，false: 不使用紧凑模式输出
     */
    public boolean isCompact() {
        return getBoolean(Function.compact, false);
    }

    /**
     * 设置Json输出格式的紧凑模式
     *
     * @param compact
     *            true: 使用紧凑模式输出，false: 不使用紧凑模式输出
     * @return 该Json输出格式
     */
    public JsonFormat setCompact(boolean compact) {
        put(Function.compact, compact);
        return this;
    }

    @Deprecated
    public int getIndent() {
        return 0;
    }

    @Deprecated
    public JsonFormat setIndent(int indent) {
        return this;
    }

    @Deprecated
    public JsonFormat increaseIndent() {
        return this;
    }

    @Deprecated
    public JsonFormat decreaseIndent() {
        return this;
    }

    /**
     * Json输出格式的缩进时用的字符串
     *
     * @return 缩进时用的字符串
     */
    public String getIndentBy() {
        return getString(Function.indentBy, "   ");
    }
    /**
     * 设置忽略 JsonShape 注解
     * @return
     */
    public JsonFormat ignoreJsonShape() {
		put(Function.ignoreJsonShape,true);
		return this;
	}

    public boolean isIgnoreJsonShape() {
		return getBoolean(Function.ignoreJsonShape);
	}

    /**
     * 设置Json输出格式的缩进时用的字符串
     *
     * @param indentBy
     *            设置缩进时用的字符串
     * @return 该Json输出格式
     */
    public JsonFormat setIndentBy(String indentBy) {
        put(Function.indentBy, indentBy);
        return this;
    }

    /**
     * Json输出格式的给字段添加双引号
     *
     * @return 是否给字段添加双引号
     */
    public boolean isQuoteName() {
        return getBoolean(Function.quoteName, true); // 默认为true
    }

    /**
     * 设置Json输出格式的给字段添加双引号
     *
     * @param quoteName
     *            true: 给字段添加双引号，false: 不给字段添加双引号
     * @return 该Json输出格式
     */
    public JsonFormat setQuoteName(boolean quoteName) {
        put(Function.quoteName, quoteName);
        return this;
    }

    /**
     * Json输出格式的忽略null值
     *
     * @return 是否忽略null的值
     */
    public boolean isIgnoreNull() {
        return getBoolean(Function.ignoreNull, false);
    }

    /**
     * 设置Json输出格式中是否忽略null
     *
     * @param ignoreNull
     *            true: 忽略null的值，false: 不忽略null的值
     * @return 该Json输出格式
     */
    public JsonFormat setIgnoreNull(boolean ignoreNull) {
        put(Function.ignoreNull, ignoreNull);
        return this;
    }

    /**
     * 设置Json输出格式中输出的字段
     *
     * @param regex
     *            输出的字段的正则表达式
     * @return 该Json输出格式
     */
    public JsonFormat setActived(String regex) {
        put(Function.actived, Pattern.compile(regex));
        return this;
    }

    /**
     * 设置Json输出格式中不输出的字段
     *
     * @param regex
     *            不输出的字段的正则表达式
     * @return 该Json输出格式
     */
    public JsonFormat setLocked(String regex) {
        put(Function.locked, Pattern.compile(regex));
        return this;
    }

    public Castors getCastors() {
        return castors == null ? Castors.me() : castors;
    }

    public JsonFormat setCastors(Castors castors) {
        this.castors = castors;
        return this;
    }

    /**
     * 设置Json输出格式的分隔符
     *
     * @param separator
     *            分隔符
     * @return 该Json输出格式
     */
    public JsonFormat setSeparator(char separator) {
        put(Function.separator, separator);
        return this;
    }

    /**
     * Json输出格式的分隔符
     *
     * @return 分隔符
     */
    public char getSeparator() {
        Character separator = getAs(Function.separator, Character.class);
        if (separator != null)
            return separator;
        return DEFAULT_SEPARATOR;
    }

    /**
     * 设置Json输出格式的自动将值应用unicode编码
     *
     * @param autoUnicode
     *            true: 自动将值应用unicode编码，false: 不自动将值应用unicode编码
     * @return 该Json输出格式
     */
    public JsonFormat setAutoUnicode(boolean autoUnicode) {
        put(Function.autoUnicode, autoUnicode);
        return this;
    }

    /**
     * Json输出格式的自动unicode编码
     *
     * @return true: 自动将值应用unicode编码，false: 不自动将值应用unicode编码
     */
    public boolean isAutoUnicode() {
        return getBoolean(Function.autoUnicode, false);
    }

    /**
     * Json输出格式的unicode编码
     *
     * @return true: unicode编码用大写，false: unicode编码用小写
     */
    public boolean isUnicodeLower() {
        return getBoolean(Function.unicodeLower, false);
    }

    /**
     * 设置Json输出格式的unicode编码大小写规则
     *
     * @param unicodeLower
     *            true: unicode编码用大写，false: unicode编码用小写
     * @return 该Json输出格式
     */
    public JsonFormat setUnicodeLower(boolean unicodeLower) {
        put(Function.unicodeLower, unicodeLower);
        return this;
    }

    /**
     * 设置Json输出格式的设置日期格式
     *
     * @param df
     *            日期格式
     * @return 该Json输出格式
     */
    public JsonFormat setDateFormat(String df) {
        if (df == null) {
            remove(Function.dateFormat);
        } else if (DATEFORMAT_TIMESTAMP.equals(df)) {
            put(Function.dateFormat, new TimeStampDateFormat());
        } else {
            put(Function.dateFormat, new SimpleDateFormat(df));
            put(Function.dateFormatRaw, df);
        }
        return this;
    }

    /**
     * 设置Json输出格式的日期格式
     *
     * @param df
     *            日期格式
     * @return 该Json输出格式
     */
    public JsonFormat setDateFormat(DateFormat df) {
        put(Function.dateFormat, df);
        return this;
    }

    /**
     * Json输出格式的日期格式
     *
     * @return 日期格式
     */
    public DateFormat getDateFormat() {
        DateFormat df = getAs(Function.dateFormat, DateFormat.class);
        return df == null ? null : (DateFormat) df.clone();
    }

    /**
     * Json输出格式的数字格式
     *
     * @return 数字格式
     */
    public NumberFormat getNumberFormat() {
        NumberFormat nf = getAs(Function.numberFormat, NumberFormat.class);
        return nf == null ? null : (NumberFormat) nf.clone();
    }

    /**
     * 设置Json输出格式的数字格式
     *
     * @param numberFormat
     *            数字格式
     * @return 该Json输出格式
     */
    public JsonFormat setNumberFormat(NumberFormat numberFormat) {
        put(Function.numberFormat, numberFormat);
        return this;
    }

    /**
     * 生成一个该Json输出格式的副本
     *
     * @return 该Json输出格式的副本
     */
    @Override
    public JsonFormat clone() {
        JsonFormat jf = new JsonFormat();
        jf.putAll(this);
        return jf;
    }

    public static String DATEFORMAT_TIMESTAMP = "timestamp";

    public Pattern getActived() {
        return getAs(Function.actived, Pattern.class);
    }

    public JsonFormat setActived(Pattern actived) {
        put(Function.actived, actived);
        return this;
    }

    public Pattern getLocked() {
        return getAs(Function.locked, Pattern.class);
    }

    public JsonFormat setLocked(Pattern locked) {
        put(Function.locked, locked);
        return this;
    }

    public boolean isNullAsEmtry() {
        return getBoolean(Function.nullAsEmtry, false);
    }

    public JsonFormat setNullAsEmtry(boolean nullAsEmtry) {
        put(Function.nullAsEmtry, nullAsEmtry);
        return this;
    }

    public TimeZone getTimeZone() {
        return getAs(Function.timeZone, TimeZone.class);
    }

    public JsonFormat setTimeZone(TimeZone timeZone) {
        put(Function.timeZone, timeZone);
        return this;
    }

    public boolean isNullListAsEmpty() {
        return getBoolean(Function.nullListAsEmpty, false);
    }

    public JsonFormat setNullListAsEmpty(boolean nullListAsEmpty) {
        put(Function.nullListAsEmpty, nullListAsEmpty);
        return this;
    }

    public boolean isNullStringAsEmpty() {
        return getBoolean(Function.nullStringAsEmpty, false);
    }

    public JsonFormat setNullStringAsEmpty(boolean nullStringAsEmpty) {
        put(Function.nullStringAsEmpty, nullStringAsEmpty);
        return this;
    }

    public boolean isNullBooleanAsFalse() {
        return getBoolean(Function.nullBooleanAsFalse, false);
    }

    public JsonFormat setNullBooleanAsFalse(boolean nullBooleanAsFalse) {
        put(Function.nullBooleanAsFalse, nullBooleanAsFalse);
        return this;
    }

    public boolean isNullNumberAsZero() {
        return getBoolean(Function.nullNumberAsZero, false);
    }

    public JsonFormat setNullNumberAsZero(boolean nullNumberAsZero) {
        put(Function.nullNumberAsZero, nullNumberAsZero);
        return this;
    }

    public JsonFormat setLocale(String locale) {
        put(Function.locale, locale);
        return this;
    }

    public String getLocale() {
        return getString(Function.locale);
    }

    public String getDateFormatRaw() {
        return getString(Function.dateFormatRaw);
    }
}


package org.nutz.json;

import static org.nutz.lang.Streams.buffr;
import static org.nutz.lang.Streams.fileInr;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.nutz.json.entity.JsonEntity;
import org.nutz.json.handler.JsonArrayHandler;
import org.nutz.json.handler.JsonBooleanHandler;
import org.nutz.json.handler.JsonClassHandler;
import org.nutz.json.handler.JsonDateTimeHandler;
import org.nutz.json.handler.JsonEnumHandler;
import org.nutz.json.handler.JsonIterableHandler;
import org.nutz.json.handler.JsonJsonRenderHandler;
import org.nutz.json.handler.JsonLocalDateLikeHandler;
import org.nutz.json.handler.JsonMapHandler;
import org.nutz.json.handler.JsonMirrorHandler;
import org.nutz.json.handler.JsonNumberHandler;
import org.nutz.json.handler.JsonPojoHandler;
import org.nutz.json.handler.JsonStringLikeHandler;
import org.nutz.json.impl.JsonEntityFieldMakerImpl;
import org.nutz.json.impl.JsonRenderImpl;
import org.nutz.lang.Files;
import org.nutz.lang.Lang;
import org.nutz.lang.Mirror;
import org.nutz.lang.Streams;
import org.nutz.lang.util.NutType;
import org.nutz.lang.util.PType;
import org.nutz.mapl.Mapl;

public class Json {

    // =========================================================================
    // ============================Json.fromJson================================
    // =========================================================================
    /**
     * 从文本输入流中生成 JAVA 对象。
     *
     * @param reader
     *            文本输入流
     * @return JAVA 对象
     * @throws JsonException
     */
    public static Object fromJson(Reader reader) throws JsonException {
        // return new org.nutz.json.impl.JsonCompileImpl().parse(reader);
        return new org.nutz.json.impl.JsonCompileImplV2().parse(reader);
    }

    /**
     * 根据指定的类型，从文本输入流中生成 JAVA 对象。 指定的类型可以是任意 JAVA 对象。
     *
     * @param type
     *            对象类型
     * @param reader
     *            文本输入流
     * @return 指定类型的 JAVA 对象
     * @throws JsonException
     */
    @SuppressWarnings("unchecked")
    public static <T> T fromJson(Class<T> type, Reader reader)
            throws JsonException {
        return (T) parse(type, reader);
    }

    /**
     * 根据指定的类型，从文本输入流中生成 JAVA 对象。 指定的类型可以是任意 JAVA 对象。
     *
     * @param type
     *            对象类型，可以是范型
     * @param reader
     *            文本输入流
     * @return 指定类型的 JAVA 对象
     * @throws JsonException
     */
    public static Object fromJson(Type type, Reader reader)
            throws JsonException {
        return parse(type, reader);
    }

    private static Object parse(Type type, Reader reader) {
        Object obj = fromJson(reader);
        if (type != null)
            return Mapl.maplistToObj(obj, type);
        return obj;
    }

    /**
     * 根据指定的类型，从字符串中生成 JAVA 对象。 指定的类型可以是任意 JAVA 对象。
     *
     * @param type
     *            对象类型，可以是范型
     * @param cs
     *            JSON 字符串
     * @return 指定类型的 JAVA 对象
     * @throws JsonException
     */
    public static Object fromJson(Type type, CharSequence cs)
            throws JsonException {
        return fromJson(type, Lang.inr(cs));
    }

    @SuppressWarnings("unchecked")
    public static <T> T fromJson(PType<T> type, Reader reader)
            throws JsonException {
        return (T) fromJson((Type)type, reader);
    }

    @SuppressWarnings("unchecked")
    public static <T> T fromJson(PType<T> type, CharSequence cs)
            throws JsonException {
        return (T)fromJson((Type)type, cs);
    }

    /**
     * 根据指定的类型，读取指定的 JSON 文件生成 JAVA 对象。 指定的类型可以是任意 JAVA 对象。
     *
     * @param type
     *            对象类型
     * @param f
     *            文件对象
     * @return 指定类型的 JAVA 对象
     * @throws JsonException
     */
    public static <T> T fromJsonFile(Class<T> type, File f) {
        BufferedReader br = null;
        try {
            br = buffr(fileInr(f));
            return Json.fromJson(type, br);
        }
        finally {
            Streams.safeClose(br);
        }
    }

    /**
     * 从 JSON 字符串中，获取 JAVA 对象。 实际上，它就是用一个 Read 包裹了的字符串。
     *

     * 请参看函数 ‘Object fromJson(Reader reader)’ 的描述
     *
     * @param cs
     *            JSON 字符串
     * @return JAVA 对象
     * @throws JsonException
     *
     * @see #fromJson(Reader reader)
     */
    public static Object fromJson(CharSequence cs) throws JsonException {
        return fromJson(Lang.inr(cs));
    }

    /**
     * 根据指定的类型，从字符串中生成 JAVA 对象。 指定的类型可以是任意 JAVA 对象。
     *

     * 请参看函数 ‘<T> T fromJson(Class<T> type, Reader reader)’ 的描述
     *
     * @param type
     *            对象类型
     * @param cs
     *            JSON 字符串
     * @return 特定类型的 JAVA 对象
     * @throws JsonException
     *
     * @see #fromJson(Class type, Reader reader)
     */
    public static <T> T fromJson(Class<T> type, CharSequence cs)
            throws JsonException {
        return fromJson(type, Lang.inr(cs));
    }

    // =========================================================================
    // ============================Json.toJson==================================
    // =========================================================================
    private static Class<? extends JsonRender> jsonRenderCls;

    public static Class<? extends JsonRender> getJsonRenderCls() {
        return jsonRenderCls;
    }

    public static void setJsonRenderCls(Class<? extends JsonRender> cls) {
        jsonRenderCls = cls;
    }

    /**
     * 将一个 JAVA 对象转换成 JSON 字符串
     *
     * @param obj
     *            JAVA 对象
     * @return JSON 字符串
     */
    public static String toJson(Object obj) {
        return toJson(obj, null);
    }

    /**
     * 将一个 JAVA 对象转换成 JSON 字符串，并且可以设定 JSON 字符串的格式化方式
     *
     * @param obj
     *            JAVA 对象
     * @param format
     *            JSON 字符串格式化方式 ，若 format 为 null ，则以 JsonFormat.nice() 格式输出
     * @return JSON 字符串
     */
    public static String toJson(Object obj, JsonFormat format) {
        StringBuilder sb = new StringBuilder();
        toJson(Lang.opw(sb), obj, format);
        return sb.toString();
    }

    /**
     * 将一个 JAVA 对象以 JSON 的形式写到一个文本输出流里
     *
     * @param writer
     *            文本输出流
     * @param obj
     *            JAVA 对象
     */
    public static void toJson(Writer writer, Object obj) {
        toJson(writer, obj, null);
    }

    /**
     * 将一个 JAVA 对象以 JSON 的形式写到一个文本输出流里，并且可以设定 JSON 字符串的格式化方式
     *
     * @param writer
     *            文本输出流
     * @param obj
     *            JAVA 对象
     * @param format
     *            JSON 字符串格式化方式 ，若 format 为 null ，则以 JsonFormat.nice() 格式输出
     */
    public static void toJson(Writer writer, Object obj, JsonFormat format) {
        try {
            if (format == null)
                format = deft;
            JsonRender jr;
            Class<? extends JsonRender> jrCls = getJsonRenderCls();
            if (jrCls == null)
                jr = new JsonRenderImpl();
            else
            	jr = Mirror.me(jrCls).born();
            jr.setWriter(writer);
            jr.setFormat(format);
            jr.render(obj);

            writer.flush();
        }
        catch (IOException e) {
            throw Lang.wrapThrow(e, JsonException.class);
        }
    }

    /**
     * 将一个 JAVA 对象以 JSON 的形式写到一个文件里
     *
     * @param f
     *            文本文件
     * @param obj
     *            JAVA 对象
     */
    public static void toJsonFile(File f, Object obj) {
        toJsonFile(f, obj, null);
    }

    /**
     * 将一个 JAVA 对象以 JSON 的形式写到一个文件里，并且可以设定 JSON 字符串的格式化方式
     *
     * @param f
     *            文本文件
     * @param obj
     *            JAVA 对象
     * @param format
     *            JSON 字符串格式化方式 ，若 format 为 null ，则以 JsonFormat.nice() 格式输出
     */
    public static void toJsonFile(File f, Object obj, JsonFormat format) {
        Writer writer = null;
        try {
            Files.createFileIfNoExists(f);
            writer = Streams.fileOutw(f);
            Json.toJson(writer, obj, format);
            writer.append('\n');
        }
        catch (IOException e) {
            throw Lang.wrapThrow(e);
        }
        finally {
            Streams.safeClose(writer);
        }
    }

    /**
     * 清除 Json 解析器对实体解析的缓存
     */
    public static void clearEntityCache() {
        entities.clear();
    }

    /**
     * 保存所有的 Json 实体
     */
    private static final ConcurrentHashMap<String, JsonEntity> entities = new ConcurrentHashMap<String, JsonEntity>();

    /**
     * 获取一个 Json 实体
     */
    public static JsonEntity getEntity(Mirror<?> mirror) {
        JsonEntity je = entities.get(mirror.getTypeId());
        if (null == je) {
            je = new JsonEntity(mirror);
            entities.put(mirror.getTypeId(), je);
        }
        return je;
    }

    // ==================================================================================
    // ====================帮助函数======================================================

    /**
     * 从 JSON 字符串中，根据获取某种指定类型的 List 对象。
     *

     * 请参看函数 ‘Object fromJson(Type type, CharSequence cs)’ 的描述
     *
     * @param eleType
     *            对象类型
     * @param cs
     *            JSON 字符串
     * @return 特定类型的 JAVA 对象
     * @throws JsonException
     *
     * @see #fromJson(Type type, CharSequence cs)
     */
    @SuppressWarnings("unchecked")
    public static <T> List<T> fromJsonAsList(Class<T> eleType, CharSequence cs) {
        return (List<T>) fromJson(NutType.list(eleType), cs);
    }

    /**
     * 从 JSON 输入流中，根据获取某种指定类型的 List 对象。
     *

     * 请参看函数 ‘Object fromJson(Type type, Reader reader)’ 的描述
     *
     * @param eleType
     *            对象类型
     * @param reader
     *            JSON 输入流
     * @return 特定类型的 JAVA 对象
     * @throws JsonException
     *
     * @see #fromJson(Type type, Reader reader)
     */
    @SuppressWarnings("unchecked")
    public static <T> List<T> fromJsonAsList(Class<T> eleType, Reader reader) {
        return (List<T>) fromJson(NutType.list(eleType), reader);
    }

    /**
     * 从 JSON 字符串中，根据获取某种指定类型的 数组 对象。
     *

     * 请参看函数 ‘Object fromJson(Type type, CharSequence cs)’ 的描述
     *
     * @param eleType
     *            对象类型
     * @param cs
     *            JSON 字符串
     * @return 特定类型的 JAVA 对象
     * @throws JsonException
     *
     * @see #fromJson(Type type, CharSequence cs)
     */
    @SuppressWarnings("unchecked")
    public static <T> T[] fromJsonAsArray(Class<T> eleType, CharSequence cs) {
        return (T[]) fromJson(NutType.array(eleType), cs);
    }

    /**
     * 从 JSON 输入流中，根据获取某种指定类型的 数组 对象。
     *

     * 请参看函数 ‘Object fromJson(Type type, Reader reader)’ 的描述
     *
     * @param eleType
     *            对象类型
     * @param reader
     *            JSON 输入流
     * @return 特定类型的 JAVA 对象
     * @throws JsonException
     *
     * @see #fromJson(Class type, Reader reader)
     */
    @SuppressWarnings("unchecked")
    public static <T> T[] fromJsonAsArray(Class<T> eleType, Reader reader) {
        return (T[]) fromJson(NutType.array(eleType), reader);
    }

    /**
     * 从 JSON 字符串中，根据获取某种指定类型的 Map 对象。
     *

     * 请参看函数 ‘Object fromJson(Type type, CharSequence cs)’ 的描述
     *
     * @param eleType
     *            对象类型
     * @param cs
     *            JSON 字符串
     * @return 特定类型的 JAVA 对象
     * @throws JsonException
     *
     * @see #fromJson(Type type, CharSequence cs)
     */
    @SuppressWarnings("unchecked")
    public static <T> Map<String, T> fromJsonAsMap(Class<T> eleType,
                                                   CharSequence cs) {
        return (Map<String, T>) fromJson(NutType.mapStr(eleType), cs);
    }

    /**
     * 从 JSON 输入流中，根据获取某种指定类型的 Map 对象。
     *

     * 请参看函数 ‘Object fromJson(Type type, Reader reader)’ 的描述
     *
     * @param eleType
     *            对象类型
     * @param reader
     *            JSON 输入流
     * @return 特定类型的 JAVA 对象
     * @throws JsonException
     *
     * @see #fromJson(Type type, Reader reader)
     */
    @SuppressWarnings("unchecked")
    public static <T> Map<String, T> fromJsonAsMap(Class<T> eleType,
                                                   Reader reader) {
        return (Map<String, T>) fromJson(NutType.mapStr(eleType), reader);
    }

    protected static JsonFormat deft = JsonFormat.nice();
    public static void setDefaultJsonformat(JsonFormat defaultJf) {
        if (defaultJf == null)
            defaultJf = JsonFormat.nice();
        Json.deft = defaultJf;
    }

    private static JsonEntityFieldMaker deftMaker = new JsonEntityFieldMakerImpl();
    public static void setDefaultFieldMaker(JsonEntityFieldMaker fieldMaker) {
        if (fieldMaker != null)
            Json.deftMaker = fieldMaker;
    }
    public static JsonEntityFieldMaker getDefaultFieldMaker() {
        return deftMaker;
    }
    protected static List<JsonTypeHandler> handlers = new ArrayList<JsonTypeHandler>();
    public static void addTypeHandler(JsonTypeHandler handler) {
        if (!handlers.contains(handler))
            handlers.add(0, handler);
    }
    public static List<JsonTypeHandler> getTypeHandlers() {
        return Collections.unmodifiableList(handlers);
    }

    /**
     *
     */
    static {
        handlers.add(new JsonJsonRenderHandler());
        handlers.add(new JsonClassHandler());
        handlers.add(new JsonMirrorHandler());
        handlers.add(new JsonEnumHandler());
        handlers.add(new JsonNumberHandler());
        handlers.add(new JsonBooleanHandler());
        handlers.add(new JsonStringLikeHandler());
        handlers.add(new JsonDateTimeHandler());
        try {
            Class.forName("java.time.temporal.TemporalAccessor");
            handlers.add(new JsonLocalDateLikeHandler());
        }
        catch (Throwable e) {
        }
        handlers.add(new JsonMapHandler());
        handlers.add(new JsonIterableHandler());
        handlers.add(new JsonArrayHandler());
        handlers.add(new JsonPojoHandler());
    }
}


package org.nutz.dao.util;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.nutz.dao.Chain;
import org.nutz.dao.Condition;
import org.nutz.dao.DaoException;
import org.nutz.dao.FieldFilter;
import org.nutz.dao.FieldMatcher;
import org.nutz.dao.entity.Entity;
import org.nutz.dao.entity.EntityField;
import org.nutz.dao.entity.MappingField;
import org.nutz.dao.entity.PkType;
import org.nutz.dao.impl.jdbc.NutPojo;
import org.nutz.dao.impl.sql.pojo.ConditionPItem;
import org.nutz.dao.impl.sql.pojo.EntityTableNamePItem;
import org.nutz.dao.impl.sql.pojo.EntityViewNamePItem;
import org.nutz.dao.impl.sql.pojo.InsertFieldsPItem;
import org.nutz.dao.impl.sql.pojo.InsertValuesPItem;
import org.nutz.dao.impl.sql.pojo.PkConditionPItem;
import org.nutz.dao.impl.sql.pojo.QueryEntityFieldsPItem;
import org.nutz.dao.impl.sql.pojo.SingleColumnCondtionPItem;
import org.nutz.dao.impl.sql.pojo.SqlTypePItem;
import org.nutz.dao.impl.sql.pojo.StaticPItem;
import org.nutz.dao.impl.sql.pojo.UpdateFieldsByChainPItem;
import org.nutz.dao.impl.sql.pojo.UpdateFieldsPItem;
import org.nutz.dao.jdbc.JdbcExpert;
import org.nutz.dao.jdbc.ValueAdaptor;
import org.nutz.dao.pager.Pager;
import org.nutz.dao.sql.Criteria;
import org.nutz.dao.sql.PItem;
import org.nutz.dao.sql.Pojo;
import org.nutz.dao.sql.PojoCallback;
import org.nutz.dao.sql.SqlType;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.log.Log;
import org.nutz.log.Logs;

public abstract class Pojos {

	public static final Log log = Logs.get();

	// ==========================================================
	// 以下是创建 POJO 语句元素的帮助方法
	public static class Items {

		public static PItem sqlType() {
			return new SqlTypePItem();
		}

		public static PItem entityTableName() {
			return new EntityTableNamePItem();
		}

		public static PItem entityViewName() {
			return new EntityViewNamePItem();
		}

		public static PItem wrap(String str) {
			return new StaticPItem(str);
		}

		public static PItem wrapf(String fmt, Object... args) {
			return new StaticPItem(String.format(fmt, args));
		}

		public static PItem insertFields() {
			return new InsertFieldsPItem();
		}

		public static PItem insertValues() {
			return new InsertValuesPItem();
		}

		public static PItem updateFields(Object refer) {
			return new UpdateFieldsPItem(refer);
		}

		public static PItem updateFieldsBy(Chain chain) {
			return new UpdateFieldsByChainPItem(chain);
		}

		public static PItem queryEntityFields() {
			return new QueryEntityFieldsPItem();
		}

		public static PItem cndId(Entity<?> en, Number id) {
		    MappingField mappingField = en.getIdField();
		    if (mappingField == null)
		        throw new DaoException("expect @Id but NOT found. " + en.getType().getName());
			return cndColumn(mappingField, id);
		}

		public static PItem cndName(Entity<?> en, String name) {
		    MappingField mappingField = en.getNameField();
            if (mappingField == null)
                throw new DaoException("expect @Name but NOT found. " + en.getType().getName());
			return cndColumn(mappingField, name);
		}

		public static PItem cndColumn(MappingField mappingField, Object def) {
			SingleColumnCondtionPItem re = new SingleColumnCondtionPItem(mappingField, def);
			re.setCasesensitive(mappingField.isCasesensitive());
			return re;
		}

		public static PItem cndColumn(String colName, MappingField mappingField, Object def) {
			return new SingleColumnCondtionPItem(	colName,
													mappingField.getTypeClass(),
													mappingField.getAdaptor(),
													def);
		}

		public static PItem cndPk(Entity<?> en, Object[] pks) {
			ValueAdaptor[] vas = new ValueAdaptor[en.getCompositePKFields().size()];
			int i = 0;
			for (MappingField mf : en.getCompositePKFields())
				vas[i++] = mf.getAdaptor();
			return new PkConditionPItem(vas, pks);
		}

		public static PItem cndAuto(Entity<?> en, Object obj) {
			obj = Lang.first(obj);
			switch (en.getPkType()) {
			case ID:
				Number id = null != obj ? ((Number) en.getIdField().getValue(obj)) : null;
				if (id == null && (en.getNameField() != null)) {
					String name = (String) en.getNameField().getValue(obj);
					if (!Strings.isBlank(name)) {
						return cndName(en, name);
					}
				}
				return cndId(en, id);
			case NAME:
				String name = null != obj ? Strings.sNull(en.getNameField().getValue(obj), null) : null;
				return cndName(en, name);
			case COMPOSITE:
				Object[] pks = null;
				if (null != obj) {
					pks = new Object[en.getCompositePKFields().size()];
					int i = 0;
					for (EntityField ef : en.getCompositePKFields())
						pks[i++] = ef.getValue(obj);
				}
				return cndPk(en, pks);
			default:
				if (Map.class.isAssignableFrom(en.getType())) {
					return null; // Map形式的话,不一定需要主键嘛
				}
				throw Lang.makeThrow("Don't know how to make fetch key %s:'%s', need any of @Id/@Name/@Pk", en.getType()
																					.getName(), obj);
			}
		}

		public static PItem[] cnd(Condition cnd) {
			List<PItem> list = new LinkedList<PItem>();
			if (null == cnd) {}
			// 高级条件
			else if (cnd instanceof Criteria) {
				list.add((Criteria) cnd);
			}
			// 普通条件
			else {
				list.add(new ConditionPItem(cnd));
			}
			return list.toArray(new PItem[list.size()]);
		}

		public static Pager pager(Condition cnd) {
			if (null == cnd) {
				return null;
			}
			// 高级条件
			else if (cnd instanceof Criteria) {
				return ((Criteria) cnd).getPager();
			}
			// 普通条件
			else {
				return null;
			}
		}

	}

	// 以上是创建 POJO 语句元素的帮助方法
	// ==========================================================

	public static Pojo createRun(PojoCallback callback) {
		return new NutPojo().setSqlType(SqlType.RUN).setAfter(callback);
	}

    public static List<MappingField> getFieldsForInsert(Entity<?> en, FieldMatcher fm) {
        List<MappingField> re = new ArrayList<MappingField>(en.getMappingFields().size());
        for (MappingField mf : en.getMappingFields()) {
            if (null == fm || fm.match(mf.getName())) {
                if (!mf.isAutoIncreasement() && !mf.isReadonly() && mf.isInsert()) {
                    re.add(mf);
                } else if (fm != null && mf.isId() && !fm.isIgnoreId()) {
                    re.add(mf);
                }
            }
        }
        if (re.isEmpty() && log.isDebugEnabled())
            log.debug("none field for insert!");
        return re;
    }

	public static List<MappingField> getFieldsForUpdate(Entity<?> en, FieldMatcher fm, Object refer) {
		List<MappingField> re = new ArrayList<MappingField>(en.getMappingFields().size());
        Object tmp = Lang.first(refer);
		for (MappingField mf : en.getMappingFields()) {
			if (mf.isPk()) {
				if (en.getPkType() == PkType.ID && mf.isId())
					continue;
				if (en.getPkType() == PkType.NAME && mf.isName())
					continue;
				if (en.getPkType() == PkType.COMPOSITE && mf.isCompositePk())
					continue;
			}
			if (mf.isReadonly() || mf.isAutoIncreasement() || !mf.isUpdate())
				continue;
			if (fm == null) {
			    re.add(mf);
			}
			else if (tmp == null) {
			    if (fm.match(mf.getName()))
			        re.add(mf);
			}
			else {
			    if (fm.match(mf, tmp))
			        re.add(mf);
			}
		}
		if (re.isEmpty() && log.isDebugEnabled())
			log.debug("none field for update!");
		return re;
	}

	private static final Pattern ptn = Pattern.compile(	"^(WHERE|ORDER BY)(.+)",
														Pattern.CASE_INSENSITIVE);

	public static String formatCondition(Entity<?> en, Condition cnd) {
		return formatCondition(en, cnd, true);
	}

	public static String formatCondition(Entity<?> en, Condition cnd, boolean top) {
        if (null != cnd) {
            String str = Strings.trim(cnd.toSql(en));
            if (top && !ptn.matcher(str).find())
                return "WHERE " + str;
            return str;
        }
        return "";
    }

	public static Pojo pojo(JdbcExpert expert, Entity<?> en, SqlType type) {
		Pojo pojo = expert.createPojo(type);
		pojo.getContext().setFieldMatcher(FieldFilter.get(en.getType()));
		return pojo;
	}

}


package org.nutz.el.parse;

import java.io.Reader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.nutz.el.ElException;
import org.nutz.el.Parse;
import org.nutz.el.obj.Elobj;
import org.nutz.el.obj.FieldObj;
import org.nutz.el.obj.IdentifierObj;
import org.nutz.el.obj.MethodObj;
import org.nutz.el.opt.arithmetic.LBracketOpt;
import org.nutz.el.opt.arithmetic.NegativeOpt;
import org.nutz.el.opt.arithmetic.RBracketOpt;
import org.nutz.el.opt.arithmetic.SubOpt;
import org.nutz.el.opt.object.AccessOpt;
import org.nutz.el.opt.object.CommaOpt;
import org.nutz.el.opt.object.InvokeMethodOpt;
import org.nutz.el.opt.object.MethodOpt;
import org.nutz.lang.Lang;

/**
 * 转换器,也就是用来将字符串转换成队列. TODO 这个类的名字不知道取什么好...
 *
 * @author juqkai(juqkai@gmail.com)
 *
 */
public class Converter {
    private final List<Parse> parses = new ArrayList<Parse>();

    // 表达式字符队列
    private CharQueue exp;
    // 表达式项
    private LinkedList<Object> itemCache;
    // 方法栈
    private LinkedList<MethodOpt> methods = new LinkedList<MethodOpt>();

    // 上一个数据
    private Object prev = null;

    public Converter(CharQueue reader) {
        this.exp = reader;
        itemCache = new LinkedList<Object>();
        skipSpace();
        initParse();
    }

    public Converter(String val) {
        this(Lang.inr(val));
    }

    public Converter(Reader reader) {
        this(new CharQueueDefault(reader));
    }

    /**
     * 初始化解析器
     */
    private void initParse() {
        parses.add(new OptParse());
        parses.add(new StringParse());
        parses.add(new IdentifierParse());
        parses.add(new ValParse());
    }

    /**
     * 重新设置解析器
     */
    public void setParse(List<Parse> val) {
        parses.addAll(val);
    }

    /**
     * 初始化EL项
     */
    public void initItems() {
        while (!exp.isEmpty()) {
            Object obj = parseItem();
            // 处理数组的情况
            if (obj.getClass().isArray()) {
                for (Object o : (Object[]) obj) {
                    itemCache.add(o);
                }
                continue;
            }
            itemCache.add(obj);
        }
        itemCache = clearUp(itemCache);
    }

    /**
     * 清理转换后的结果, 主要做一些标识性的转换
     *
     * @param rpn
     * @return
     */
    private LinkedList<Object> clearUp(LinkedList<Object> rpn) {
        LinkedList<Object> dest = new LinkedList<Object>();
        while (!rpn.isEmpty()) {
            if (!(rpn.getFirst() instanceof Elobj)) {
                dest.add(rpn.removeFirst());
                continue;
            }
            Elobj obj = (Elobj) rpn.removeFirst();
            // 方法对象
            if (!rpn.isEmpty() && rpn.getFirst() instanceof MethodOpt) {
                dest.add(new MethodObj(obj.getVal()));
                continue;
            }
            // 属性对象
            if (dest.size() > 0
                && dest.getLast() instanceof AccessOpt
                && rpn.size() > 0
                && rpn.getFirst() instanceof AccessOpt) {
                dest.add(new FieldObj(obj.getVal()));
                continue;
            }
            // //普通的对象
            // if(!(dest.getLast() instanceof AccessOpt) && !(rpn.peekFirst()
            // instanceof MethodOpt)){
            // continue;
            // }
            dest.add(new IdentifierObj(obj.getVal()));
        }
        return dest;
    }

    /**
     * 解析数据
     */
    private Object parseItem() {
        Object obj = Parse.nullobj;
        for (Parse parse : parses) {
            obj = parse.fetchItem(exp);
            if (obj != Parse.nullobj) {
                skipSpace();
                return parseItem(obj);
            }
        }
        throw new ElException("无法解析!");
    }

    /**
     * 转换数据,主要是转换负号,方法执行
     */
    private Object parseItem(Object item) {
        // 处理参数个数
        if (methods.peek() != null) {
            MethodOpt opt = methods.peek();
            if (opt.getSize() <= 0) {
                if (!(item instanceof CommaOpt) && !(item instanceof RBracketOpt)) {
                    opt.setSize(1);
                }
            } else {
                if (item instanceof CommaOpt) {
                    opt.setSize(opt.getSize() + 1);
                }
            }
        }

        // 左括号
        if (item instanceof LBracketOpt) {
            if (prev instanceof Elobj) {
                MethodOpt prem = new MethodOpt();
                item = new Object[]{prem, new LBracketOpt()};
                methods.addFirst(prem);
            } else {
                methods.addFirst(null);
            }
        }

        // 右括号
        if (item instanceof RBracketOpt) {
            if (methods.poll() != null) {
                item = new Object[]{new RBracketOpt(), new InvokeMethodOpt()};
            }
        }
        // 转换负号'-'
        if (item instanceof SubOpt && NegativeOpt.isNegetive(prev)) {
            item = new NegativeOpt();
        }
        prev = item;
        return item;
    }

    /**
     * 跳过空格,并返回是否跳过空格(是否存在空格)
     */
    private boolean skipSpace() {
        boolean space = false;
        while (!exp.isEmpty() && Character.isWhitespace(exp.peek())) {
            space = true;
            exp.poll();
        }
        return space;
    }

    /**
     * 取得一个有效数据
     */
    public Object fetchItem() {
        return itemCache.poll();
    }

    /**
     * 是否结束
     */
    public boolean isEnd() {
        return itemCache.isEmpty();
    }
}


package org.nutz.ioc;

import java.util.Map;
import java.util.Map.Entry;

import org.nutz.ioc.meta.IocEventSet;
import org.nutz.ioc.meta.IocField;
import org.nutz.ioc.meta.IocObject;
import org.nutz.ioc.meta.IocValue;
import org.nutz.ioc.val.StaticValue;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.meta.Pair;
import org.nutz.lang.util.Regex;

/**
 * @author zozoh(zozohtnt@gmail.com)
 * @author wendal(wendal1985@gmail.com)
 *
 */
public abstract class Iocs {

    private static final String OBJFIELDS = "^(type|scope|singleton|fields|args|events|factory)$";

    public static boolean isIocObject(Map<String, ?> map) {
        for (Entry<String, ?> en : map.entrySet())
            if (!Regex.match(OBJFIELDS, en.getKey()))
                return false;
        return true;
    }

    public static Pair<Class<?>> parseName(String name) {
        String _name = null;
        Class<?> type = null;
        int pos = name.indexOf(':');
        if (pos < 0) {
            _name = Strings.trim(name);
        } else {
            _name = Strings.trim(name.substring(0, pos));
            try {
                String typeName = Strings.trim(name.substring(pos + 1));
                type = Lang.loadClass(typeName);
            }
            catch (ClassNotFoundException e) {
                throw Lang.wrapThrow(e);
            }
        }
        return new Pair<Class<?>>(_name, type);
    }

    /**
     * 查看一下 me 中有没有缺少的属性，没有的话，从 it 补充
     */
    public static IocObject mergeWith(IocObject me, IocObject it) {
        // merge type
        if (me.getType() == null)
            me.setType(it.getType());

        // don't need merge singleton

        // merge events
        if (me.getEvents() == null) {
            me.setEvents(it.getEvents());
        } else if (it.getEvents() != null) {
            IocEventSet eventSet = it.getEvents();
            IocEventSet myEventSet = me.getEvents();
            if (Strings.isBlank(myEventSet.getCreate()))
                myEventSet.setCreate(eventSet.getCreate());
            if (Strings.isBlank(myEventSet.getDepose()))
                myEventSet.setDepose(eventSet.getDepose());
            if (Strings.isBlank(myEventSet.getFetch()))
                myEventSet.setFetch(eventSet.getFetch());
        }

        // merge scope
        if (Strings.isBlank(me.getScope())) {
            me.setScope(it.getScope());
        }

        // merge arguments
        if (!me.hasArgs())
            me.copyArgys(it.getArgs());

        // merge fields
        for (IocField fld : it.getFields().values())
            if (!me.hasField(fld.getName()))
                me.addField(fld);

        return me;
    }

    public static IocValue convert(String value, boolean dftRefer) {
        IocValue iocValue = new IocValue();
        if (dftRefer && value.startsWith(":")) {
            iocValue.setType(IocValue.TYPE_NORMAL);
            iocValue.setValue(value.substring(1));
//        } else if (value.startsWith("$")) {
//            iocValue.setType(IocValue.TYPE_REFER);
//            iocValue.setValue(value.substring(1));
        }
        else if (value.contains(":")) {
            String type = value.substring(0, value.indexOf(':'));
            if (IocValue.types.contains(type)) {
                iocValue.setType(type);
                if (value.endsWith(":")) {
                    iocValue.setValue("");
                }
                else
                    iocValue.setValue(value.substring(value.indexOf(':') + 1));
            } else {
                iocValue.setType(IocValue.TYPE_NORMAL);
                iocValue.setValue(value);
            }
        } else {
            // XXX 兼容性改变, 1.b.52 开始默认就是refer, 如果真的要输入常量
            //log.info("auto set as         refer:" + value);
            iocValue.setType(IocValue.TYPE_REFER);
            iocValue.setValue(value);
        }
        return iocValue;
    }

    public static Object self(Object obj) {
        return obj;
    }

    public static IocObject wrap(Object obj) {
        IocObject iobj = new IocObject();
        if (obj != null)
            iobj.setType(obj.getClass());
        iobj.setFactory(Iocs.class.getName() + "#self");
        IocValue ival = new IocValue(null, new StaticValue(obj));
        iobj.addArg(ival);
        return iobj;
    }
}


package org.nutz.mvc.impl;

import java.lang.reflect.Method;

import org.nutz.mvc.adaptor.AbstractAdaptor;
import org.nutz.mvc.adaptor.ParamInjector;

/**
 * 当这个类作为参数声明在入口方法时,当适配器产生错误时,将注入到你的方法中

 * 这是很普通的类,但,请发挥你的创造力,这可是一个扩展点啊! 你可以继承这个类,
 * @author wendal
 *
 */
public class AdaptorErrorContext {

    /**
     * 构建一个适配器错误上下文,由AbstractAdaptor创建

     * 子类必须有这个构造方法!!
     * @param size 必须等于入口方法的参数数量
     */
    public AdaptorErrorContext(int size) {
        errors = new Throwable[size];
    }

    /**
     * 具体参数导致的异常信息
     */
    protected Throwable[] errors;

    /**
     * 获取具体参数的异常信息,与参数的顺序一致, 其中会包含null(尤其是最后一个参数,因为就是本类)
     */
    public Throwable[] getErrors() {
        return errors;
    }

    /**
     * 设置当前参数的错误信息,是子类可以无限扩展的地方
     * @param index 参数的索引号
     * @param err   参数注入器抛出的异常,建议先用Lang.unwarp(err)解开,获取真正的异常
     * @param method 入口方法
     * @param value  期待转换的值
     * @param inj    参数注入器
     */
    public void setError(int index, Throwable err, Method method, Object value, ParamInjector inj) {
        errors[index] = err;
    }

    /**
     * 适配器本身导致的异常,例如JsonAdaptor读取到错误的Json字符串, UploadAdaptor读取到错误的上传信息
     */
    protected Throwable adaptorErr;

    public void setAdaptorError(Throwable err, AbstractAdaptor adaptor) {
        this.adaptorErr = err;
    }

    /**
     * 适配器本身导致的异常,例如JsonAdaptor读取到错误的Json字符串, UploadAdaptor读取到错误的上传信息
     */
    public Throwable getAdaptorErr() {
        return adaptorErr;
    }
}


package org.nutz.lang.tmpl;

import java.util.LinkedList;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutBean;
import org.nutz.lang.util.NutMap;

/**
 * 占位符支持 `${路径<类型:格式>?默认值}` 的写法
 *

 * 支持的类型为:
 *

 *
int : %d 格式化字符串
 *
long : %d 格式化字符串
 *
float : %f 格式化字符串
 *
double: %f 格式化字符串
 *
boolean: 否/是 格式化字符串
 *
date : yyyyMMdd 格式化字符串
 *
string: %s 格式化字符串。或者 (string::A=Apple,B=Banana,C=Cherry) 表映射数据
 *
json : cqn 输出一段 JSON 文本,c紧凑，q输出引号,n忽略null
 *

 *

 * 如果没有声明类型，则当做 "string"
 *
 * @author zozoh(zozohtnt@gmail.com)
 */
public class Tmpl {

    // private static final Pattern _P2 =
    // Pattern.compile("([\\w\\d_.\\[\\]'\"-]+)"
    // + "(<(int|long|boolean|float|double|date|string)( *: *([^>]*))?>)?"
    // + "([?] *(.*) *)?");

    private static final Pattern _P2 = Pattern.compile("([^<>()?]+)"
                                                       + "([<(](int|long|boolean|float|double|date|string|json)?( *: *([^>]*))?[>)])?"
                                                       + "([?] *(.*) *)?");

    /**
     * 解析模板对象
     *
     * @param tmpl
     *            模板字符串
     * @return 解析好的模板对象
     *
     * @see #parse(String, Pattern, int, int)
     */
    public static Tmpl parse(String tmpl) {
        if (null == tmpl)
            return null;
        return new Tmpl(tmpl, null, -1, -1, null);
    }

    public static Tmpl parsef(String fmt, Object... args) {
        if (null == fmt)
            return null;
        return new Tmpl(String.format(fmt, args), null, -1, -1, null);
    }

    /**
     * 解析模板对象，并用上下文进行渲染。
     *

     * 你可以通过参数 ptn 指定自定义的正则表达式来声明自己的模板占位符形式。

     * 默认的模板占位符是 (?<![$])[$][{]([^}]+)[}]
     *

     * 即，形式如 ${xxxx} 的会被当做占位符， 同时 $$ 可以逃逸
     *
     * @param tmpl
     *            模板字符串
     * @param ptn
     *            一个正则表达式，指明占位符的形式。
     * @param groupIndex
     *            指定正则表达式，哪个匹配组作为你的占位符内容
     * @param escapeIndex
     *            指明了逃逸字符的组，如果为 -1 则表示没有逃逸字符
     * @param getEscapeStr
     *            给定如何显示逃逸字符的回调
     * @return 模板对象
     */
    public static Tmpl parse(String tmpl,
                             Pattern ptn,
                             int groupIndex,
                             int escapeIndex,
                             TmplEscapeStr getEscapeStr) {
        if (null == tmpl)
            return null;
        return new Tmpl(tmpl, ptn, groupIndex, escapeIndex, getEscapeStr);
    }

    /**
     * 解析模板对象, 并用上下文进行渲染。
     *
     * @param tmpl
     *            模板字符串
     * @param startChar
     *            占位符起始标示符
     * @param leftBrace
     *            左侧括号
     * @param rightBrace
     *            右侧括号
     * @return 模板对象
     */
    public static Tmpl parse(String tmpl,
                             final String startChar,
                             String leftBrace,
                             String rightBrace) {
        if (null == tmpl)
            return null;
        String regex = "((?<!["
                       + startChar
                       + "])["
                       + startChar
                       + "]["
                       + ("[".equals(leftBrace) ? "\\[" : leftBrace)
                       + "]([^"
                       + ("]".equals(rightBrace) ? "\\]" : rightBrace)
                       + "]+)["
                       + rightBrace
                       + "])|(["
                       + startChar
                       + "]["
                       + startChar
                       + "])";
        Pattern ptn = Pattern.compile(regex);
        return new Tmpl(tmpl, ptn, 2, 3, new TmplEscapeStr() {
            public String get(Matcher m) {
                return startChar;
            }
        });
    }

    /**
     * 自定义占位符的开始字符，左右括号各为 "{" 和 "}"
     *
     * @see #parse(String, String, String, String)
     */
    public static Tmpl parse(String tmpl, final String startChar) {
        return parse(tmpl, startChar, "{", "}");
    }

    /**
     * @see #exec(String, Pattern, int, int, NutBean, boolean)
     */
    public static String exec(String tmpl, NutBean context) {
        return exec(tmpl, null, -1, -1, null, context, true);
    }

    /**
     * @see #exec(String, Pattern, int, int, NutBean, boolean)
     */
    public static String exec(String tmpl, NutBean context, boolean showKey) {
        return exec(tmpl, null, -1, -1, null, context, showKey);
    }

    /**
     * @see #parse(String, Pattern, int, int, TmplEscapeStr)
     */
    public static String exec(String tmpl,
                              Pattern ptn,
                              int groupIndex,
                              int escapeIndex,
                              TmplEscapeStr getEscapeStr,
                              NutBean context,
                              boolean showKey) {
        return parse(tmpl, ptn, groupIndex, escapeIndex, getEscapeStr).render(context, showKey);
    }

    /**
     * @see #parse(String, String, String, String)
     */
    public static String exec(String tmpl,
                              String startChar,
                              String leftBrace,
                              String rightBrace,
                              NutBean context,
                              boolean showKey) {
        return parse(tmpl, startChar, leftBrace, rightBrace).render(context, showKey);
    }

    /**
     * @see #parse(String, String)
     */
    public static String exec(String tmpl, String startChar, NutBean context, boolean showKey) {
        return parse(tmpl, startChar).render(context, showKey);
    }

    private Pattern _P;
    int groupIndex;
    int escapeIndex;
    private TmplEscapeStr getEscapeStr;
    private List<TmplEle> list;
    private List<String> keys;

    private Tmpl() {
        list = new LinkedList<TmplEle>();
        keys = new LinkedList<String>();
    }

    private Tmpl(Pattern ptn, int grpIdx, int escIdx, TmplEscapeStr getEscapeStr) {
        this();
        // 默认的模板占位符
        if (null == ptn) {
            // _P =
            // Pattern.compile("((?<![$])[$][{]([^}]+)[}])|([$]([$][{][^}]+[}]))");
            // this.groupIndex = 2;
            // this.escapeIndex = 4;

            _P = Pattern.compile("((?<![$])[$][{]([^}]+)[}])|([$][$])");
            this.groupIndex = 2;
            this.escapeIndex = 3;
            this.getEscapeStr = new TmplEscapeStr() {
                public String get(Matcher m) {
                    return "$";
                }
            };
        }
        // 自定义的占位符
        else {
            _P = ptn;
            this.groupIndex = grpIdx;
            this.escapeIndex = escIdx;
            this.getEscapeStr = getEscapeStr;
            if (null == this.getEscapeStr) {
                this.getEscapeStr = new TmplEscapeStr() {
                    public String get(Matcher m) {
                        return m.group(escapeIndex).substring(0, 1);
                    }
                };
            }
        }
    }

    private Tmpl(String tmpl,
                 Pattern ptn,
                 int groupIndex,
                 int escapeIndex,
                 TmplEscapeStr getEscapeStr) {
        this(ptn, groupIndex, escapeIndex, getEscapeStr);

        // 开始解析
        Matcher m = _P.matcher(tmpl);
        int lastIndex = 0;

        while (m.find()) {
            int pos = m.start();
            // 看看是否要生成静态对象
            if (pos > lastIndex) {
                list.add(new TmplStaticEle(tmpl.substring(lastIndex, pos)));
            }

            // 看看是逃逸呢，还是匹配上了
            String s_escape = this.escapeIndex > 0 ? m.group(this.escapeIndex) : null;
            String s_match = m.group(this.groupIndex);

            // 如果是逃逸
            if (!Strings.isBlank(s_escape)) {
                String esc_str = this.getEscapeStr.get(m);
                list.add(new TmplStaticEle(esc_str));
            }
            // 否则分析键
            else {
                // 如果是 `=` 开头，直接就作为字符串好了
                // 这个特殊处理，可以用来把占位符和 El 结合起来
                // 如果想输出一个占位符是 El 表达式，那么写个 = ， 就会被认为是字符串默认保留
                // 如果渲染的时候，对 key 进行判断，发现是 = 开头的 key，用 El 预先渲染并填入上下文就好了
                // TODO 这个是不是应该搞一个 TmplElEle 呢？
                if (s_match.startsWith("=")) {
                    keys.add(s_match);
                    list.add(new TmplStringEle(s_match, null, null));
                }
                // 否则根据占位符语法解析一下
                else {
                    Matcher m2 = _P2.matcher(s_match);

                    if (!m2.find())
                        throw Lang.makeThrow("Fail to parse tmpl key '%s'", m.group(1));

                    String key = m2.group(1);
                    String type = Strings.sNull(m2.group(3), "string");
                    String fmt = m2.group(5);
                    String dft = m2.group(7);

                    // 记录键
                    keys.add(key);

                    // 创建元素
                    if ("string".equals(type)) {
                        list.add(new TmplStringEle(key, fmt, dft));
                    }
                    // int
                    else if ("int".equals(type)) {
                        list.add(new TmplIntEle(key, fmt, dft));
                    }
                    // long
                    else if ("long".equals(type)) {
                        list.add(new TmplLongEle(key, fmt, dft));
                    }
                    // boolean
                    else if ("boolean".equals(type)) {
                        list.add(new TmplBooleanEle(key, fmt, dft));
                    }
                    // float
                    else if ("float".equals(type)) {
                        list.add(new TmplFloatEle(key, fmt, dft));
                    }
                    // double
                    else if ("double".equals(type)) {
                        list.add(new TmplDoubleEle(key, fmt, dft));
                    }
                    // date
                    else if ("date".equals(type)) {
                        list.add(new TmplDateEle(key, fmt, dft));
                    }
                    // json
                    else if ("json".equals(type)) {
                        list.add(new TmplJsonEle(key, fmt, dft));
                    }
                    // 靠不可能
                    else {
                        throw Lang.impossible();
                    }
                }
            }
            // 记录
            lastIndex = m.end();
        }

        // 最后结尾是否要加入一个对象
        if (!(lastIndex >= tmpl.length())) {
            list.add(new TmplStaticEle(tmpl.substring(lastIndex)));
        }

    }

    public String render(NutBean context) {
        return render(context, true);
    }

    public String render(NutBean context, boolean showKey) {
        StringBuilder sb = new StringBuilder();
        if (null == context)
            context = new NutMap();
        for (TmplEle ele : list) {
            ele.join(sb, context, showKey);
        }
        return sb.toString();
    }

    public List<String> keys() {
        return this.keys;
    }

    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (TmplEle ele : list) {
            sb.append(ele);
        }
        return sb.toString();
    }

}