Package org.nutz.ioc.java

Source Code of org.nutz.ioc.java.ChainParsing

package org.nutz.ioc.java;

import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.util.LinkedArray;
import org.nutz.lang.util.LinkedCharArray;

public class ChainParsing {

  private char[] cs;
  private int i;
  private ChainNode first;
  private ChainNode last;
  /**
   * 如果不为 null,那么 addNode 将全加到这里
   */
  private LinkedArray<LinkedArray<ChainNode>> argss;
  /**
   * 控制 parse 函数,合适退出
   */
  private LinkedCharArray ends;
  /**
   * parse 函数所使用的字符缓冲区
   */
  private StringBuilder sb;

  public ChainParsing(String s) {
    ends = new LinkedCharArray(10);
    sb = new StringBuilder();
    argss = new LinkedArray<LinkedArray<ChainNode>>(5);
    cs = s.toCharArray();
    parse();
  }

  private void parse() {
    for (; i < cs.length; i++) {
      char c = cs[i];
      if (c == ',') {
        checkIfNeedAddNode();
      }
      // String
      else if (c == '\'' || c == '"') {
        clearStringBuffer();
        for (i++; i < cs.length; i++) {
          char n = cs[i];
          if (n == c)
            break;
          sb.append(n);
        }
        addNode(new StringNode(clearStringBuffer()));
      }
      // @Ioc | @Context | @Name
      else if (c == '@') {
        String name = readToDot().toUpperCase();
        if ("IOC".equals(name)) {
          addNode(new IocSelfNode());
        } else if ("CONTEXT".equals(name)) {
          addNode(new IocContextNode());
        } else if ("NAME".equals(name)) {
          addNode(new IocObjectNameNode());
        }
        continue;
      }
      // $xxx
      else if (c == '$') {
        String name = readToDot();
        addNode(new IocObjectNode(name));
        continue;
      }
      // (...) in func
      else if (c == '(') {
        String funcName = Strings.trim(clearStringBuffer());
        argss.push(new LinkedArray<ChainNode>(ChainNode.class, 5));
        ends.push(')');
        i++;
        parse();
        ends.popLast();
        ChainNode[] args = argss.popLast().toArray();
        int pos = funcName.lastIndexOf('.');
        if (pos > 0) {
          String className = funcName.substring(0, pos);
          funcName = funcName.substring(pos + 1);
          addNode(new StaticFunctionNode(className, funcName, args));
        } else {
          addNode(new ObjectFunctionNode(funcName, args));
        }
        clearStringBuffer();
      }
      // If funcs, it will will quit when encounter the ')'
      else if (ends.size() > 0 && c == ends.last()) {
        checkIfNeedAddNode();
        return;
      }
      // xxx.xxx.xxx
      else {
        sb.append(c);
      }
    }
    checkIfNeedAddNode();
  }

  private void checkIfNeedAddNode() {
    // Finished Parsing, check the buffer
    if (!Strings.isBlank(sb)) {
      String s = Strings.trim(clearStringBuffer());
      // null
      if (s.equalsIgnoreCase("null")) {
        addNode(new NullNode());
      }
      // boolean
      else if (s.matches("^(true|false)$")) {
        addNode(new BooleanNode(s));
      }
      // number
      else if (s.matches("^([0-9]+)$")) {
        addNode(new NumberNode(s));
      }
      // the chain is empty
      else if (null == last) {
        int pos = s.lastIndexOf('.');
        if (pos < 0)
          throw Lang.makeThrow("Don't know how to invoke '%s'", s);
        String className = s.substring(0, pos);
        String funcName = s.substring(pos + 1);
        addNode(new StaticFunctionNode(className, funcName, new ChainNode[0]));
      }
      // some node had been built
      else {
        addNode(new FieldNode(s));
      }
    }
  }

  private String readToDot() {
    for (i++; i < cs.length; i++) {
      char c = cs[i];
      if (c == '.' || c == ',')
        break;
      sb.append(c);
    }
    return clearStringBuffer();
  }

  private String clearStringBuffer() {
    String re = Strings.trim(sb);
    sb = new StringBuilder();
    return re;
  }

  private void addNode(ChainNode node) {
    // For arguments
    if (argss.size() > 0) {
      argss.last().push(node);
    }
    // First time
    else if (last == null) {
      first = node;
      last = node;
    }
    // Normal ...
    else {
      last.setNext(node);
      last = node;
    }
  }

  public ChainNode getNode() {
    return first;
  }

}
TOP

Related Classes of org.nutz.ioc.java.ChainParsing

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.