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.