Package org.nutz.lang.segment

Source Code of org.nutz.lang.segment.CharSegment

package org.nutz.lang.segment;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.nutz.lang.Lang;
import org.nutz.lang.Mirror;
import org.nutz.lang.util.Context;
import org.nutz.lang.util.NutMap;

public class CharSegment implements Segment, Cloneable {

    public CharSegment() {}

    public CharSegment(String str) {
        valueOf(str);
    }

    @SuppressWarnings("unchecked")
    public Segment add(String key, Object v) {
        if (!context.has(key)) {
            context.set(key, v);
            return this;
        }
        Object val = context.get(key);
        if (val == null) {
            context.set(key, v);
        } else if (val instanceof Collection<?>) {
            ((Collection<Object>) val).add(v);
        } else {
            List<Object> objSet = new LinkedList<Object>();
            objSet.add(val);
            objSet.add(v);
            context.set(key, objSet);
        }
        return this;
    }

    public void clearAll() {
        context.clear();
    }

    public boolean contains(String key) {
        return keys.containsKey(key);
    }

    public Segment born() {
        return new CharSegment(this.getOrginalString());
    }

    private String orgString;

    public String getOrginalString() {
        return orgString;
    }

    public Segment clone() {
        CharSegment cs = new CharSegment();
        cs.parse(Lang.inr(orgString));
        cs.context = this.context.clone();
        return cs;
    }

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

    public int keyCount() {
        return this.keys.size();
    }

    public boolean hasKey() {
        return !this.keys.isEmpty();
    }

    public List<Object> values() {
        List<Object> re = new ArrayList<Object>(nodes.size());
        for (SegmentNode node : nodes) {
            if (node.isKey())
                re.add(context.get(node.getValue()));
            else
                re.add(node.getValue());
        }
        return re;
    }

    public Segment setAll(Object v) {
        for (String key : keys())
            context.set(key, v);
        return this;
    }

    public Segment setBy(Object obj) {
        Iterator<String> it = keys().iterator();
        Class<?> klass = obj.getClass();
        Mirror<?> mirror = Mirror.me(klass);
        // Primitive Type: set it to all PlugPoints
        if (mirror.isStringLike() || mirror.isBoolean() || mirror.isNumber() || mirror.isChar()) {
            this.setAll(obj);
        }
        // Map: set by key
        else if (mirror.isOf(Map.class)) {
            Map<?, ?> map = (Map<?, ?>) obj;
            while (it.hasNext()) {
                String key = it.next();
                try {
                    this.set(key, map.get(key));
                }
                catch (Exception e) {
                    this.set(key, "");
                }
            }
        }
        // POJO: set by field
        else {
            while (it.hasNext()) {
                String key = it.next();
                try {
                    this.set(key, mirror.getValue(obj, key));
                }
                catch (Exception e) {
                    this.set(key, "");
                }
            }
        }
        return this;
    }

    public Segment set(String key, Object v) {
        context.set(key, v);
        return this;
    }

    public List<SegmentNode> getNodes() {
        return nodes;
    }

    private Context context;

    private List<SegmentNode> nodes;

    private NutMap keys;

    public void parse(Reader reader) {
        nodes = new LinkedList<SegmentNode>();
        context = Lang.context();
        keys = new NutMap();
        StringBuilder org = new StringBuilder();
        StringBuilder sb = new StringBuilder();
        int b;
        try {
            while (-1 != (b = reader.read())) {
                org.append((char) b);
                switch (b) {
                case '$':
                    b = reader.read();
                    org.append((char) b);
                    // Escape
                    if (b == '$') {
                        sb.append((char) b);
                    }
                    // In Plug Point
                    else if (b == '{') {
                        // Save before
                        if (sb.length() > 0) {
                            nodes.add(SegmentNode.val(sb.toString()));
                            sb = new StringBuilder();
                        }
                        // Search the end
                        while (-1 != (b = reader.read())) {
                            org.append((char) b);
                            if (b == '}')
                                break;
                            sb.append((char) b);
                        }
                        if (b != '}')
                            throw Lang.makeThrow("Error format around '%s'", sb);
                        // Create Key
                        String key = sb.toString();
                        nodes.add(SegmentNode.key(key));
                        keys.put(key, null);
                        sb = new StringBuilder();
                    }
                    // Normal
                    else {
                        sb.append('$').append((char) b);
                    }
                    break;
                default:
                    sb.append((char) b);
                }
            }
            if (sb.length() > 0)
                nodes.add(SegmentNode.val(sb.toString()));
            // Store the Oraginal Value
            orgString = org.toString();
        }
        catch (IOException e) {
            throw Lang.wrapThrow(e);
        }
    }

    public Segment valueOf(String str) {
        parse(new StringReader(str));
        return this;
    }

    public CharSequence render() {
        return render(context);
    }

    public CharSequence render(Context context) {
        StringBuilder sb = new StringBuilder();
        for (SegmentNode node : nodes) {
            Object val = node.isKey() ? context.get(node.getValue()) : node.getValue();
            if (null == val)
                continue;
            if (val instanceof Collection<?>) {
                for (Object obj : (Collection<?>) val) {
                    sb.append(obj);
                }
            } else {
                sb.append(val);
            }
        }
        return sb;
    }

    public Context getContext() {
        return context;
    }

    public void fillNulls(Context context) {
        for (String key : keys.keySet()) {
            Object val = context.get(key);
            if (null == val)
                context.set(key, "${" + key + "}");
        }
    }

    public String toString() {
        return render().toString();
    }

}
TOP

Related Classes of org.nutz.lang.segment.CharSegment

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.