Browse Source

变更sybotan为saga.

sybotan 5 years ago
parent
commit
d0963c9a3c

+ 2 - 2
build.gradle

@@ -21,8 +21,8 @@
  * ********************************************************************************************************************
  */
 
-group 'com.sybotan'
-version SYBOTAN_KOTLIN_VERSION
+group 'cn.sagacloud'
+version SAGA_KOTLIN_VERSION
 
 buildscript {
     repositories {

+ 2 - 2
gradle.properties

@@ -21,8 +21,8 @@
 # *********************************************************************************************************************
 #
 
-SAGA_URL = http://www.sybotan.com
-SAGA_KOTLIN_VERSION = 1.4.92
+SAGA_URL = http://www.sagacloud.cn
+SAGA_KOTLIN_VERSION = 1.4.94
 # android
 # SYBOTAN_KOTLIN_VERSION = 1.4.63
 

BIN
gradle/wrapper/gradle-wrapper.jar


+ 5 - 0
gradle/wrapper/gradle-wrapper.properties

@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists

+ 172 - 0
gradlew

@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"

+ 84 - 0
gradlew.bat

@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega

+ 1 - 1
saga-kotlin-base/build.gradle

@@ -97,7 +97,7 @@ uploadArchives {
             pom.project {
                 name project.name
                 packaging 'jar'
-                url SYBOTAN_URL
+                url SAGA_URL
                 description '斯伯坦机器人 Kotlin 基础支持库。'
                 licenses {
                     license {

+ 2 - 2
saga-kotlin-database/build.gradle

@@ -61,7 +61,7 @@ dependencies {
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // Sybotan依赖
-    compile project(':sybotan-kotlin-base')
+    compile project(':saga-kotlin-base')
 
 //    // https://mvnrepository.com/artifact/net.java.dev.javacc/javacc
 //    compile group: 'net.java.dev.javacc', name: 'javacc', version: '6.1.2'
@@ -108,7 +108,7 @@ uploadArchives {
             pom.project {
                 name project.name
                 packaging "jar"
-                url SYBOTAN_URL
+                url SAGA_URL
                 description "斯伯坦机器人 Kotlin 数据库操作支持库。"
                 licenses {
                     license {

+ 2 - 1
saga-kotlin-database/src/main/kotlin/com/sybotan/database/SAbstractDao.kt

@@ -368,8 +368,9 @@ abstract class SAbstractDao<ENTITY: Any>(entityClazz: Class<ENTITY>) {
      * @param   id1         对象表ID字段名
      * @param   id2         级联对象ID字段名
      * @param   self        自身级联
+     * @param   filter      附加过滤条件
      * @param   idList      对象ID列表
      * @return  关系列表
      */
-    abstract fun relationQuery(table: String, id1: String, id2: String, self: Boolean, idList: ArrayList<Any>): ArrayList<HashMap<String, Any>>
+    abstract fun relationQuery(table: String, id1: String, id2: String, self: Boolean, filter: String, idList: ArrayList<Any>): ArrayList<HashMap<String, Any>>
 } // Class SAbstractDao

+ 193 - 0
saga-kotlin-database/src/main/kotlin/com/sybotan/database/parser/ParseException.java

@@ -0,0 +1,193 @@
+/* Generated By:JavaCC: Do not edit this line. ParseException.java Version 6.1 */
+/* JavaCCOptions:KEEP_LINE_COLUMN=true */
+package com.sybotan.database.parser;
+
+/**
+ * This exception is thrown when parse errors are encountered.
+ * You can explicitly create objects of this exception type by
+ * calling the method generateParseException in the generated
+ * parser.
+ *
+ * You can modify this class to customize your error reporting
+ * mechanisms so long as you retain the public fields.
+ */
+public class ParseException extends Exception {
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * The end of line string for this machine.
+   */
+  protected static String EOL = System.getProperty("line.separator", "\n");
+
+  /**
+   * This constructor is used by the method "generateParseException"
+   * in the generated parser.  Calling this constructor generates
+   * a new object of this type with the fields "currentToken",
+   * "expectedTokenSequences", and "tokenImage" set.
+   */
+  public ParseException(Token currentTokenVal,
+                        int[][] expectedTokenSequencesVal,
+                        String[] tokenImageVal
+                       )
+  {
+    super(initialise(currentTokenVal, expectedTokenSequencesVal, tokenImageVal));
+    currentToken = currentTokenVal;
+    expectedTokenSequences = expectedTokenSequencesVal;
+    tokenImage = tokenImageVal;
+  }
+
+  /**
+   * The following constructors are for use by you for whatever
+   * purpose you can think of.  Constructing the exception in this
+   * manner makes the exception behave in the normal way - i.e., as
+   * documented in the class "Throwable".  The fields "errorToken",
+   * "expectedTokenSequences", and "tokenImage" do not contain
+   * relevant information.  The JavaCC generated code does not use
+   * these constructors.
+   */
+
+  public ParseException() {
+    super();
+  }
+
+  /** Constructor with message. */
+  public ParseException(String message) {
+    super(message);
+  }
+
+
+  /**
+   * This is the last token that has been consumed successfully.  If
+   * this object has been created due to a parse error, the token
+   * followng this token will (therefore) be the first error token.
+   */
+  public Token currentToken;
+
+  /**
+   * Each entry in this array is an array of integers.  Each array
+   * of integers represents a sequence of tokens (by their ordinal
+   * values) that is expected at this point of the parse.
+   */
+  public int[][] expectedTokenSequences;
+
+  /**
+   * This is a reference to the "tokenImage" array of the generated
+   * parser within which the parse error occurred.  This array is
+   * defined in the generated ...Constants interface.
+   */
+  public String[] tokenImage;
+
+  /**
+   * It uses "currentToken" and "expectedTokenSequences" to generate a parse
+   * error message and returns it.  If this object has been created
+   * due to a parse error, and you do not catch it (it gets thrown
+   * from the parser) the correct error message
+   * gets displayed.
+   */
+  private static String initialise(Token currentToken,
+                           int[][] expectedTokenSequences,
+                           String[] tokenImage) {
+
+    StringBuffer expected = new StringBuffer();
+    int maxSize = 0;
+    for (int i = 0; i < expectedTokenSequences.length; i++) {
+      if (maxSize < expectedTokenSequences[i].length) {
+        maxSize = expectedTokenSequences[i].length;
+      }
+      for (int j = 0; j < expectedTokenSequences[i].length; j++) {
+        expected.append(tokenImage[expectedTokenSequences[i][j]]).append(' ');
+      }
+      if (expectedTokenSequences[i][expectedTokenSequences[i].length - 1] != 0) {
+        expected.append("...");
+      }
+      expected.append(EOL).append("    ");
+    }
+    String retval = "Encountered \"";
+    Token tok = currentToken.next;
+    for (int i = 0; i < maxSize; i++) {
+      if (i != 0) retval += " ";
+      if (tok.kind == 0) {
+        retval += tokenImage[0];
+        break;
+      }
+      retval += " " + tokenImage[tok.kind];
+      retval += " \"";
+      retval += add_escapes(tok.image);
+      retval += " \"";
+      tok = tok.next;
+    }
+    retval += "\" at line " + currentToken.next.beginLine + ", column " + currentToken.next.beginColumn;
+    retval += "." + EOL;
+    
+    
+    if (expectedTokenSequences.length == 0) {
+        // Nothing to add here
+    } else {
+	    if (expectedTokenSequences.length == 1) {
+	      retval += "Was expecting:" + EOL + "    ";
+	    } else {
+	      retval += "Was expecting one of:" + EOL + "    ";
+	    }
+	    retval += expected.toString();
+    }
+    
+    return retval;
+  }
+
+
+  /**
+   * Used to convert raw characters to their escaped version
+   * when these raw version cannot be used as part of an ASCII
+   * string literal.
+   */
+  static String add_escapes(String str) {
+      StringBuffer retval = new StringBuffer();
+      char ch;
+      for (int i = 0; i < str.length(); i++) {
+        switch (str.charAt(i))
+        {
+           case '\b':
+              retval.append("\\b");
+              continue;
+           case '\t':
+              retval.append("\\t");
+              continue;
+           case '\n':
+              retval.append("\\n");
+              continue;
+           case '\f':
+              retval.append("\\f");
+              continue;
+           case '\r':
+              retval.append("\\r");
+              continue;
+           case '\"':
+              retval.append("\\\"");
+              continue;
+           case '\'':
+              retval.append("\\\'");
+              continue;
+           case '\\':
+              retval.append("\\\\");
+              continue;
+           default:
+              if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+                 String s = "0000" + Integer.toString(ch, 16);
+                 retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+              } else {
+                 retval.append(ch);
+              }
+              continue;
+        }
+      }
+      return retval.toString();
+   }
+
+}
+/* JavaCC - OriginalChecksum=2a9aa79f05fd2cd321e6404b99a8efc4 (do not edit this line) */

+ 536 - 0
saga-kotlin-database/src/main/kotlin/com/sybotan/database/parser/SSyntaxParser.java

@@ -0,0 +1,536 @@
+/* SSyntaxParser.java */
+/* Generated By:JavaCC: Do not edit this line. SSyntaxParser.java */
+package com.sybotan.database.parser;
+
+import com.sybotan.database.*;
+import com.sybotan.database.enums.*;
+import java.util.*;
+
+public class SSyntaxParser implements SSyntaxParserConstants {
+    public List<SFilter> parserFilters() throws ParseException {
+        return parserFilterList();
+    } // Fun parserFilters()
+
+    public List<SOrder> parserOrders() throws ParseException {
+        return parserOrderList();
+    }
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 解�过滤�件列表
+  final public List<SFilter> parserFilterList() throws ParseException {Token t;
+    ArrayList<SFilter> filterList = new ArrayList<SFilter>();
+    SFilter filter;
+    filter = parserFilter();
+filterList.add(filter);
+    label_1:
+    while (true) {
+      switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+      case SEMICOLON:{
+        ;
+        break;
+        }
+      default:
+        jj_la1[0] = jj_gen;
+        break label_1;
+      }
+      jj_consume_token(SEMICOLON);
+      filter = parserFilter();
+filterList.add(filter);
+    }
+    jj_consume_token(0);
+{if ("" != null) return filterList;}
+    throw new Error("Missing return statement in function");
+  }
+
+/** 解�过滤�件 */
+  final public SFilter parserFilter() throws ParseException {SFilter filter;
+    filter = parserOrExpression();
+{if ("" != null) return filter;}
+    throw new Error("Missing return statement in function");
+  }
+
+/** 解�OR�算 */
+  final public SFilter parserOrExpression() throws ParseException {SFilter first;
+    SFilter second;
+    first = parserAndExpression();
+    label_2:
+    while (true) {
+      switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+      case OR:{
+        ;
+        break;
+        }
+      default:
+        jj_la1[1] = jj_gen;
+        break label_2;
+      }
+      jj_consume_token(OR);
+      second = parserAndExpression();
+first = SFilter.Companion.or(first, second);
+    }
+{if ("" != null) return first;}
+    throw new Error("Missing return statement in function");
+  }
+
+/** 解�AND�算 */
+  final public SFilter parserAndExpression() throws ParseException {SFilter first;
+    SFilter second;
+    SFilter temp;
+    first = parserPrimaryExpression();
+    label_3:
+    while (true) {
+      switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+      case AND:{
+        ;
+        break;
+        }
+      default:
+        jj_la1[2] = jj_gen;
+        break label_3;
+      }
+      jj_consume_token(AND);
+      second = parserPrimaryExpression();
+first = SFilter.Companion.and(first, second);
+    }
+{if ("" != null) return first;}
+    throw new Error("Missing return statement in function");
+  }
+
+/** 解�OR�算 */
+  final public SFilter parserPrimaryExpression() throws ParseException {SFilter filter;
+    SFilter temp;
+    switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+    case PROPERTY:{
+      filter = parserRelationalExpression();
+      break;
+      }
+    case LPAREN:{
+      jj_consume_token(LPAREN);
+      filter = parserFilter();
+      jj_consume_token(RPAREN);
+      break;
+      }
+    case NOT:{
+      jj_consume_token(NOT);
+      temp = parserFilter();
+filter = SFilter.Companion.not(temp);
+      break;
+      }
+    default:
+      jj_la1[3] = jj_gen;
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+{if ("" != null) return filter;}
+    throw new Error("Missing return statement in function");
+  }
+
+/** 解�关系表达� */
+  final public SFilter parserRelationalExpression() throws ParseException {Token property;
+    Object value = null;
+    property = jj_consume_token(PROPERTY);
+    switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+    case EQ:{
+      jj_consume_token(EQ);
+{if ("" != null) return SFilter.Companion.eq(property.image, parserValue());}
+      break;
+      }
+    case NE:{
+      jj_consume_token(NE);
+{if ("" != null) return SFilter.Companion.ne(property.image, parserValue());}
+      break;
+      }
+    case GT:{
+      jj_consume_token(GT);
+{if ("" != null) return SFilter.Companion.gt(property.image, parserValue());}
+      break;
+      }
+    case GTE:{
+      jj_consume_token(GTE);
+{if ("" != null) return SFilter.Companion.gte(property.image, parserValue());}
+      break;
+      }
+    case LT:{
+      jj_consume_token(LT);
+{if ("" != null) return SFilter.Companion.lt(property.image, parserValue());}
+      break;
+      }
+    case LTE:{
+      jj_consume_token(LTE);
+{if ("" != null) return SFilter.Companion.lte(property.image, parserValue());}
+      break;
+      }
+    case CONTAIN:{
+      jj_consume_token(CONTAIN);
+{if ("" != null) return SFilter.Companion.contain(property.image, parserString());}
+      break;
+      }
+    case STARTWITH:{
+      jj_consume_token(STARTWITH);
+{if ("" != null) return SFilter.Companion.startWith(property.image, parserString());}
+      break;
+      }
+    case ENDWITH:{
+      jj_consume_token(ENDWITH);
+{if ("" != null) return SFilter.Companion.endWith(property.image, parserString());}
+      break;
+      }
+    case ISNULL:{
+      jj_consume_token(ISNULL);
+{if ("" != null) return SFilter.Companion.isNull(property.image);}
+      break;
+      }
+    case IN:{
+      jj_consume_token(IN);
+{if ("" != null) return SFilter.Companion.inList(property.image, parserObjectList());}
+      break;
+      }
+    default:
+      jj_la1[4] = jj_gen;
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+/** 对象 */
+  final public Object parserValue() throws ParseException {Token t;
+    Object value;
+    switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+    case FLOAT:{
+      value = parserFloat();
+      break;
+      }
+    case INTEGER:{
+      value = parserInteger();
+      break;
+      }
+    case STRING:{
+      value = parserString();
+      break;
+      }
+    case FALSE:
+    case TRUE:{
+      value = parserBoolean();
+      break;
+      }
+    default:
+      jj_la1[5] = jj_gen;
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+{if ("" != null) return value;}
+    throw new Error("Missing return statement in function");
+  }
+
+/** 解�对象列表 */
+  final public List<Object> parserObjectList() throws ParseException {ArrayList<Object> list = new ArrayList<Object>();
+    Object obj = 1;
+    jj_consume_token(LBRACKET);
+    obj = parserValue();
+list.add(obj);
+    label_4:
+    while (true) {
+      switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+      case COMMA:{
+        ;
+        break;
+        }
+      default:
+        jj_la1[6] = jj_gen;
+        break label_4;
+      }
+      jj_consume_token(COMMA);
+      obj = parserValue();
+if (obj.getClass() != list.get(0).getClass()) {
+                ParseException e = new ParseException();
+                {if (true) throw e;}
+            }
+            list.add(obj);
+    }
+    jj_consume_token(RBRACKET);
+{if ("" != null) return list;}
+    throw new Error("Missing return statement in function");
+  }
+
+/** 浮点� */
+  final public Float parserFloat() throws ParseException {Token t;
+    t = jj_consume_token(FLOAT);
+{if ("" != null) return Float.parseFloat(t.image);}
+    throw new Error("Missing return statement in function");
+  }
+
+/** æ•´æ•° */
+  final public int parserInteger() throws ParseException {Token t;
+    t = jj_consume_token(INTEGER);
+{if ("" != null) return Integer.parseInt(t.image);}
+    throw new Error("Missing return statement in function");
+  }
+
+/** 字符� */
+  final public String parserString() throws ParseException {Token t;
+    t = jj_consume_token(STRING);
+{if ("" != null) return t.image.substring(1, t.image.length() - 1);}
+    throw new Error("Missing return statement in function");
+  }
+
+/** 布尔� */
+  final public Boolean parserBoolean() throws ParseException {Token t;
+    switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+    case TRUE:{
+      t = jj_consume_token(TRUE);
+{if ("" != null) return true;}
+      break;
+      }
+    case FALSE:{
+      t = jj_consume_token(FALSE);
+{if ("" != null) return false;}
+      break;
+      }
+    default:
+      jj_la1[7] = jj_gen;
+      jj_consume_token(-1);
+      throw new ParseException();
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// 解�排��件
+  final public List<SOrder> parserOrderList() throws ParseException {Token t;
+    List<SOrder> orderList = new ArrayList<SOrder>();
+    SOrder order;
+    order = parserOrder();
+orderList.add(order);
+    label_5:
+    while (true) {
+      switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+      case COMMA:{
+        ;
+        break;
+        }
+      default:
+        jj_la1[8] = jj_gen;
+        break label_5;
+      }
+      jj_consume_token(COMMA);
+      order = parserOrder();
+orderList.add(order);
+    }
+    jj_consume_token(0);
+{if ("" != null) return orderList;}
+    throw new Error("Missing return statement in function");
+  }
+
+  final public SOrder parserOrder() throws ParseException {Token property;
+    SOrder order = null;
+    property = jj_consume_token(PROPERTY);
+    switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+    case DESC:{
+      jj_consume_token(DESC);
+{if ("" != null) return new SOrder(property.image, SDirection.DESC);}
+      break;
+      }
+    default:
+      jj_la1[10] = jj_gen;
+      switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
+      case ASC:{
+        jj_consume_token(ASC);
+        break;
+        }
+      default:
+        jj_la1[9] = jj_gen;
+        ;
+      }
+{if ("" != null) return new SOrder(property.image, SDirection.ASC);}
+    }
+    throw new Error("Missing return statement in function");
+  }
+
+  /** Generated Token Manager. */
+  public SSyntaxParserTokenManager token_source;
+  SimpleCharStream jj_input_stream;
+  /** Current token. */
+  public Token token;
+  /** Next token. */
+  public Token jj_nt;
+  private int jj_ntk;
+  private int jj_gen;
+  final private int[] jj_la1 = new int[11];
+  static private int[] jj_la1_0;
+  static private int[] jj_la1_1;
+  static {
+      jj_la1_init_0();
+      jj_la1_init_1();
+   }
+   private static void jj_la1_init_0() {
+      jj_la1_0 = new int[] {0x8000,0x8000000,0x20000,0x42000100,0x11a800fc,0x20400000,0x4000,0x20400000,0x4000,0x40000,0x100000,};
+   }
+   private static void jj_la1_init_1() {
+      jj_la1_1 = new int[] {0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,};
+   }
+
+  /** Constructor with InputStream. */
+  public SSyntaxParser(java.io.InputStream stream) {
+     this(stream, null);
+  }
+  /** Constructor with InputStream and supplied encoding */
+  public SSyntaxParser(java.io.InputStream stream, String encoding) {
+    try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+    token_source = new SSyntaxParserTokenManager(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 11; i++) jj_la1[i] = -1;
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream stream) {
+     ReInit(stream, null);
+  }
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream stream, String encoding) {
+    try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
+    token_source.ReInit(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 11; i++) jj_la1[i] = -1;
+  }
+
+  /** Constructor. */
+  public SSyntaxParser(java.io.Reader stream) {
+    jj_input_stream = new SimpleCharStream(stream, 1, 1);
+    token_source = new SSyntaxParserTokenManager(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 11; i++) jj_la1[i] = -1;
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader stream) {
+	if (jj_input_stream == null) {
+      jj_input_stream = new SimpleCharStream(stream, 1, 1);
+   } else {
+      jj_input_stream.ReInit(stream, 1, 1);
+   }
+   if (token_source == null) {
+      token_source = new SSyntaxParserTokenManager(jj_input_stream);
+   }
+
+    token_source.ReInit(jj_input_stream);
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 11; i++) jj_la1[i] = -1;
+  }
+
+  /** Constructor with generated Token Manager. */
+  public SSyntaxParser(SSyntaxParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 11; i++) jj_la1[i] = -1;
+  }
+
+  /** Reinitialise. */
+  public void ReInit(SSyntaxParserTokenManager tm) {
+    token_source = tm;
+    token = new Token();
+    jj_ntk = -1;
+    jj_gen = 0;
+    for (int i = 0; i < 11; i++) jj_la1[i] = -1;
+  }
+
+  private Token jj_consume_token(int kind) throws ParseException {
+    Token oldToken;
+    if ((oldToken = token).next != null) token = token.next;
+    else token = token.next = token_source.getNextToken();
+    jj_ntk = -1;
+    if (token.kind == kind) {
+      jj_gen++;
+      return token;
+    }
+    token = oldToken;
+    jj_kind = kind;
+    throw generateParseException();
+  }
+
+
+/** Get the next Token. */
+  final public Token getNextToken() {
+    if (token.next != null) token = token.next;
+    else token = token.next = token_source.getNextToken();
+    jj_ntk = -1;
+    jj_gen++;
+    return token;
+  }
+
+/** Get the specific Token. */
+  final public Token getToken(int index) {
+    Token t = token;
+    for (int i = 0; i < index; i++) {
+      if (t.next != null) t = t.next;
+      else t = t.next = token_source.getNextToken();
+    }
+    return t;
+  }
+
+  private int jj_ntk_f() {
+    if ((jj_nt=token.next) == null)
+      return (jj_ntk = (token.next=token_source.getNextToken()).kind);
+    else
+      return (jj_ntk = jj_nt.kind);
+  }
+
+  private java.util.List<int[]> jj_expentries = new java.util.ArrayList<int[]>();
+  private int[] jj_expentry;
+  private int jj_kind = -1;
+
+  /** Generate ParseException. */
+  public ParseException generateParseException() {
+    jj_expentries.clear();
+    boolean[] la1tokens = new boolean[37];
+    if (jj_kind >= 0) {
+      la1tokens[jj_kind] = true;
+      jj_kind = -1;
+    }
+    for (int i = 0; i < 11; i++) {
+      if (jj_la1[i] == jj_gen) {
+        for (int j = 0; j < 32; j++) {
+          if ((jj_la1_0[i] & (1<<j)) != 0) {
+            la1tokens[j] = true;
+          }
+          if ((jj_la1_1[i] & (1<<j)) != 0) {
+            la1tokens[32+j] = true;
+          }
+        }
+      }
+    }
+    for (int i = 0; i < 37; i++) {
+      if (la1tokens[i]) {
+        jj_expentry = new int[1];
+        jj_expentry[0] = i;
+        jj_expentries.add(jj_expentry);
+      }
+    }
+    int[][] exptokseq = new int[jj_expentries.size()][];
+    for (int i = 0; i < jj_expentries.size(); i++) {
+      exptokseq[i] = jj_expentries.get(i);
+    }
+    return new ParseException(token, exptokseq, tokenImage);
+  }
+
+  /** Enable tracing. */
+  final public void enable_tracing() {
+  }
+
+  /** Disable tracing. */
+  final public void disable_tracing() {
+  }
+
+      // Fun parserOrders()
+} // Class SSyntaxParser
+

+ 128 - 0
saga-kotlin-database/src/main/kotlin/com/sybotan/database/parser/SSyntaxParserConstants.java

@@ -0,0 +1,128 @@
+/* Generated By:JavaCC: Do not edit this line. SSyntaxParserConstants.java */
+package com.sybotan.database.parser;
+
+
+/**
+ * Token literal values and constants.
+ * Generated by org.javacc.parser.OtherFilesGen#start()
+ */
+public interface SSyntaxParserConstants {
+
+  /** End of File. */
+  int EOF = 0;
+  /** RegularExpression Id. */
+  int EQ = 2;
+  /** RegularExpression Id. */
+  int NE = 3;
+  /** RegularExpression Id. */
+  int GTE = 4;
+  /** RegularExpression Id. */
+  int GT = 5;
+  /** RegularExpression Id. */
+  int LTE = 6;
+  /** RegularExpression Id. */
+  int LT = 7;
+  /** RegularExpression Id. */
+  int LPAREN = 8;
+  /** RegularExpression Id. */
+  int RPAREN = 9;
+  /** RegularExpression Id. */
+  int LBRACKET = 10;
+  /** RegularExpression Id. */
+  int RBRACKET = 11;
+  /** RegularExpression Id. */
+  int LBRACES = 12;
+  /** RegularExpression Id. */
+  int RBRACES = 13;
+  /** RegularExpression Id. */
+  int COMMA = 14;
+  /** RegularExpression Id. */
+  int SEMICOLON = 15;
+  /** RegularExpression Id. */
+  int DOT = 16;
+  /** RegularExpression Id. */
+  int AND = 17;
+  /** RegularExpression Id. */
+  int ASC = 18;
+  /** RegularExpression Id. */
+  int CONTAIN = 19;
+  /** RegularExpression Id. */
+  int DESC = 20;
+  /** RegularExpression Id. */
+  int ENDWITH = 21;
+  /** RegularExpression Id. */
+  int FALSE = 22;
+  /** RegularExpression Id. */
+  int IN = 23;
+  /** RegularExpression Id. */
+  int ISNULL = 24;
+  /** RegularExpression Id. */
+  int NOT = 25;
+  /** RegularExpression Id. */
+  int NOTNULL = 26;
+  /** RegularExpression Id. */
+  int OR = 27;
+  /** RegularExpression Id. */
+  int STARTWITH = 28;
+  /** RegularExpression Id. */
+  int TRUE = 29;
+  /** RegularExpression Id. */
+  int PROPERTY = 30;
+  /** RegularExpression Id. */
+  int IDENTIFIER = 31;
+  /** RegularExpression Id. */
+  int STRING = 32;
+  /** RegularExpression Id. */
+  int FLOAT = 33;
+  /** RegularExpression Id. */
+  int INTEGER = 34;
+  /** RegularExpression Id. */
+  int LETTER = 35;
+  /** RegularExpression Id. */
+  int DIGIT = 36;
+
+  /** Lexical state. */
+  int DEFAULT = 0;
+
+  /** Literal token values. */
+  String[] tokenImage = {
+    "<EOF>",
+    "<token of kind 1>",
+    "\"=\"",
+    "\"!=\"",
+    "\">=\"",
+    "\">\"",
+    "\"<=\"",
+    "\"<\"",
+    "\"(\"",
+    "\")\"",
+    "\"[\"",
+    "\"]\"",
+    "\"{\"",
+    "\"}\"",
+    "\",\"",
+    "\";\"",
+    "\".\"",
+    "<AND>",
+    "\"ASC\"",
+    "\"CONTAIN\"",
+    "\"DESC\"",
+    "\"ENDWITH\"",
+    "\"FALSE\"",
+    "\"IN\"",
+    "\"ISNULL\"",
+    "<NOT>",
+    "\"NOTNULL\"",
+    "<OR>",
+    "\"STARTWITH\"",
+    "\"TRUE\"",
+    "<PROPERTY>",
+    "<IDENTIFIER>",
+    "<STRING>",
+    "<FLOAT>",
+    "<INTEGER>",
+    "<LETTER>",
+    "<DIGIT>",
+  };
+
+}

File diff suppressed because it is too large
+ 1241 - 0
saga-kotlin-database/src/main/kotlin/com/sybotan/database/parser/SSyntaxParserTokenManager.java


+ 474 - 0
saga-kotlin-database/src/main/kotlin/com/sybotan/database/parser/SimpleCharStream.java

@@ -0,0 +1,474 @@
+/* Generated By:JavaCC: Do not edit this line. SimpleCharStream.java Version 6.1 */
+/* JavaCCOptions:STATIC=false,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package com.sybotan.database.parser;
+
+/**
+ * An implementation of interface CharStream, where the stream is assumed to
+ * contain only ASCII characters (without unicode processing).
+ */
+
+public class SimpleCharStream
+{
+/** Whether parser is static. */
+  public static final boolean staticFlag = false;
+  int bufsize;
+  int available;
+  int tokenBegin;
+/** Position in buffer. */
+  public int bufpos = -1;
+  protected int bufline[];
+  protected int bufcolumn[];
+
+  protected int column = 0;
+  protected int line = 1;
+
+  protected boolean prevCharIsCR = false;
+  protected boolean prevCharIsLF = false;
+
+  protected java.io.Reader inputStream;
+
+  protected char[] buffer;
+  protected int maxNextCharInd = 0;
+  protected int inBuf = 0;
+  protected int tabSize = 1;
+  protected boolean trackLineColumn = true;
+
+  public void setTabSize(int i) { tabSize = i; }
+  public int getTabSize() { return tabSize; }
+
+
+
+  protected void ExpandBuff(boolean wrapAround)
+  {
+    char[] newbuffer = new char[bufsize + 2048];
+    int newbufline[] = new int[bufsize + 2048];
+    int newbufcolumn[] = new int[bufsize + 2048];
+
+    try
+    {
+      if (wrapAround)
+      {
+        System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+        System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
+        buffer = newbuffer;
+
+        System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+        System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
+        bufline = newbufline;
+
+        System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+        System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
+        bufcolumn = newbufcolumn;
+
+        maxNextCharInd = (bufpos += (bufsize - tokenBegin));
+      }
+      else
+      {
+        System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+        buffer = newbuffer;
+
+        System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+        bufline = newbufline;
+
+        System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+        bufcolumn = newbufcolumn;
+
+        maxNextCharInd = (bufpos -= tokenBegin);
+      }
+    }
+    catch (Throwable t)
+    {
+      throw new Error(t.getMessage());
+    }
+
+
+    bufsize += 2048;
+    available = bufsize;
+    tokenBegin = 0;
+  }
+
+  protected void FillBuff() throws java.io.IOException
+  {
+    if (maxNextCharInd == available)
+    {
+      if (available == bufsize)
+      {
+        if (tokenBegin > 2048)
+        {
+          bufpos = maxNextCharInd = 0;
+          available = tokenBegin;
+        }
+        else if (tokenBegin < 0)
+          bufpos = maxNextCharInd = 0;
+        else
+          ExpandBuff(false);
+      }
+      else if (available > tokenBegin)
+        available = bufsize;
+      else if ((tokenBegin - available) < 2048)
+        ExpandBuff(true);
+      else
+        available = tokenBegin;
+    }
+
+    int i;
+    try {
+      if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1)
+      {
+        inputStream.close();
+        throw new java.io.IOException();
+      }
+      else
+        maxNextCharInd += i;
+      return;
+    }
+    catch(java.io.IOException e) {
+      --bufpos;
+      backup(0);
+      if (tokenBegin == -1)
+        tokenBegin = bufpos;
+      throw e;
+    }
+  }
+
+/** Start. */
+  public char BeginToken() throws java.io.IOException
+  {
+    tokenBegin = -1;
+    char c = readChar();
+    tokenBegin = bufpos;
+
+    return c;
+  }
+
+  protected void UpdateLineColumn(char c)
+  {
+    column++;
+
+    if (prevCharIsLF)
+    {
+      prevCharIsLF = false;
+      line += (column = 1);
+    }
+    else if (prevCharIsCR)
+    {
+      prevCharIsCR = false;
+      if (c == '\n')
+      {
+        prevCharIsLF = true;
+      }
+      else
+        line += (column = 1);
+    }
+
+    switch (c)
+    {
+      case '\r' :
+        prevCharIsCR = true;
+        break;
+      case '\n' :
+        prevCharIsLF = true;
+        break;
+      case '\t' :
+        column--;
+        column += (tabSize - (column % tabSize));
+        break;
+      default :
+        break;
+    }
+
+    bufline[bufpos] = line;
+    bufcolumn[bufpos] = column;
+  }
+
+/** Read a character. */
+  public char readChar() throws java.io.IOException
+  {
+    if (inBuf > 0)
+    {
+      --inBuf;
+
+      if (++bufpos == bufsize)
+        bufpos = 0;
+
+      return buffer[bufpos];
+    }
+
+    if (++bufpos >= maxNextCharInd)
+      FillBuff();
+
+    char c = buffer[bufpos];
+
+    UpdateLineColumn(c);
+    return c;
+  }
+
+  @Deprecated
+  /**
+   * @deprecated
+   * @see #getEndColumn
+   */
+
+  public int getColumn() {
+    return bufcolumn[bufpos];
+  }
+
+  @Deprecated
+  /**
+   * @deprecated
+   * @see #getEndLine
+   */
+
+  public int getLine() {
+    return bufline[bufpos];
+  }
+
+  /** Get token end column number. */
+  public int getEndColumn() {
+    return bufcolumn[bufpos];
+  }
+
+  /** Get token end line number. */
+  public int getEndLine() {
+     return bufline[bufpos];
+  }
+
+  /** Get token beginning column number. */
+  public int getBeginColumn() {
+    return bufcolumn[tokenBegin];
+  }
+
+  /** Get token beginning line number. */
+  public int getBeginLine() {
+    return bufline[tokenBegin];
+  }
+
+/** Backup a number of characters. */
+  public void backup(int amount) {
+
+    inBuf += amount;
+    if ((bufpos -= amount) < 0)
+      bufpos += bufsize;
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.Reader dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    inputStream = dstream;
+    line = startline;
+    column = startcolumn - 1;
+
+    available = bufsize = buffersize;
+    buffer = new char[buffersize];
+    bufline = new int[buffersize];
+    bufcolumn = new int[buffersize];
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.Reader dstream, int startline,
+                          int startcolumn)
+  {
+    this(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.Reader dstream)
+  {
+    this(dstream, 1, 1, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    inputStream = dstream;
+    line = startline;
+    column = startcolumn - 1;
+
+    if (buffer == null || buffersize != buffer.length)
+    {
+      available = bufsize = buffersize;
+      buffer = new char[buffersize];
+      bufline = new int[buffersize];
+      bufcolumn = new int[buffersize];
+    }
+    prevCharIsLF = prevCharIsCR = false;
+    tokenBegin = inBuf = maxNextCharInd = 0;
+    bufpos = -1;
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader dstream, int startline,
+                     int startcolumn)
+  {
+    ReInit(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.Reader dstream)
+  {
+    ReInit(dstream, 1, 1, 4096);
+  }
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+  int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+  {
+    this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, int startline,
+  int startcolumn, int buffersize)
+  {
+    this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, String encoding, int startline,
+                          int startcolumn) throws java.io.UnsupportedEncodingException
+  {
+    this(dstream, encoding, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, int startline,
+                          int startcolumn)
+  {
+    this(dstream, startline, startcolumn, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+  {
+    this(dstream, encoding, 1, 1, 4096);
+  }
+
+  /** Constructor. */
+  public SimpleCharStream(java.io.InputStream dstream)
+  {
+    this(dstream, 1, 1, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+                          int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
+  {
+    ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, int startline,
+                          int startcolumn, int buffersize)
+  {
+    ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
+  {
+    ReInit(dstream, encoding, 1, 1, 4096);
+  }
+
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream)
+  {
+    ReInit(dstream, 1, 1, 4096);
+  }
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, String encoding, int startline,
+                     int startcolumn) throws java.io.UnsupportedEncodingException
+  {
+    ReInit(dstream, encoding, startline, startcolumn, 4096);
+  }
+  /** Reinitialise. */
+  public void ReInit(java.io.InputStream dstream, int startline,
+                     int startcolumn)
+  {
+    ReInit(dstream, startline, startcolumn, 4096);
+  }
+  /** Get token literal value. */
+  public String GetImage()
+  {
+    if (bufpos >= tokenBegin)
+      return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
+    else
+      return new String(buffer, tokenBegin, bufsize - tokenBegin) +
+                            new String(buffer, 0, bufpos + 1);
+  }
+
+  /** Get the suffix. */
+  public char[] GetSuffix(int len)
+  {
+    char[] ret = new char[len];
+
+    if ((bufpos + 1) >= len)
+      System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
+    else
+    {
+      System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
+                                                        len - bufpos - 1);
+      System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
+    }
+
+    return ret;
+  }
+
+  /** Reset buffer when finished. */
+  public void Done()
+  {
+    buffer = null;
+    bufline = null;
+    bufcolumn = null;
+  }
+
+  /**
+   * Method to adjust line and column numbers for the start of a token.
+   */
+  public void adjustBeginLineColumn(int newLine, int newCol)
+  {
+    int start = tokenBegin;
+    int len;
+
+    if (bufpos >= tokenBegin)
+    {
+      len = bufpos - tokenBegin + inBuf + 1;
+    }
+    else
+    {
+      len = bufsize - tokenBegin + bufpos + 1 + inBuf;
+    }
+
+    int i = 0, j = 0, k = 0;
+    int nextColDiff = 0, columnDiff = 0;
+
+    while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
+    {
+      bufline[j] = newLine;
+      nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
+      bufcolumn[j] = newCol + columnDiff;
+      columnDiff = nextColDiff;
+      i++;
+    }
+
+    if (i < len)
+    {
+      bufline[j] = newLine++;
+      bufcolumn[j] = newCol + columnDiff;
+
+      while (i++ < len)
+      {
+        if (bufline[j = start % bufsize] != bufline[++start % bufsize])
+          bufline[j] = newLine++;
+        else
+          bufline[j] = newLine;
+      }
+    }
+
+    line = bufline[j];
+    column = bufcolumn[j];
+  }
+  boolean getTrackLineColumn() { return trackLineColumn; }
+  void setTrackLineColumn(boolean tlc) { trackLineColumn = tlc; }
+}
+/* JavaCC - OriginalChecksum=5bcd7786d65576915d555bbef2a1be57 (do not edit this line) */

+ 131 - 0
saga-kotlin-database/src/main/kotlin/com/sybotan/database/parser/Token.java

@@ -0,0 +1,131 @@
+/* Generated By:JavaCC: Do not edit this line. Token.java Version 6.1 */
+/* JavaCCOptions:TOKEN_EXTENDS=,KEEP_LINE_COLUMN=true,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
+package com.sybotan.database.parser;
+
+/**
+ * Describes the input token stream.
+ */
+
+public class Token implements java.io.Serializable {
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /**
+   * An integer that describes the kind of this token.  This numbering
+   * system is determined by JavaCCParser, and a table of these numbers is
+   * stored in the file ...Constants.java.
+   */
+  public int kind;
+
+  /** The line number of the first character of this Token. */
+  public int beginLine;
+  /** The column number of the first character of this Token. */
+  public int beginColumn;
+  /** The line number of the last character of this Token. */
+  public int endLine;
+  /** The column number of the last character of this Token. */
+  public int endColumn;
+
+  /**
+   * The string image of the token.
+   */
+  public String image;
+
+  /**
+   * A reference to the next regular (non-special) token from the input
+   * stream.  If this is the last token from the input stream, or if the
+   * token manager has not read tokens beyond this one, this field is
+   * set to null.  This is true only if this token is also a regular
+   * token.  Otherwise, see below for a description of the contents of
+   * this field.
+   */
+  public Token next;
+
+  /**
+   * This field is used to access special tokens that occur prior to this
+   * token, but after the immediately preceding regular (non-special) token.
+   * If there are no such special tokens, this field is set to null.
+   * When there are more than one such special token, this field refers
+   * to the last of these special tokens, which in turn refers to the next
+   * previous special token through its specialToken field, and so on
+   * until the first special token (whose specialToken field is null).
+   * The next fields of special tokens refer to other special tokens that
+   * immediately follow it (without an intervening regular token).  If there
+   * is no such token, this field is null.
+   */
+  public Token specialToken;
+
+  /**
+   * An optional attribute value of the Token.
+   * Tokens which are not used as syntactic sugar will often contain
+   * meaningful values that will be used later on by the compiler or
+   * interpreter. This attribute value is often different from the image.
+   * Any subclass of Token that actually wants to return a non-null value can
+   * override this method as appropriate.
+   */
+  public Object getValue() {
+    return null;
+  }
+
+  /**
+   * No-argument constructor
+   */
+  public Token() {}
+
+  /**
+   * Constructs a new token for the specified Image.
+   */
+  public Token(int kind)
+  {
+    this(kind, null);
+  }
+
+  /**
+   * Constructs a new token for the specified Image and Kind.
+   */
+  public Token(int kind, String image)
+  {
+    this.kind = kind;
+    this.image = image;
+  }
+
+  /**
+   * Returns the image.
+   */
+  public String toString()
+  {
+    return image;
+  }
+
+  /**
+   * Returns a new Token object, by default. However, if you want, you
+   * can create and return subclass objects based on the value of ofKind.
+   * Simply add the cases to the switch for all those special cases.
+   * For example, if you have a subclass of Token called IDToken that
+   * you want to create if ofKind is ID, simply add something like :
+   *
+   *    case MyParserConstants.ID : return new IDToken(ofKind, image);
+   *
+   * to the following switch statement. Then you can cast matchedToken
+   * variable to the appropriate type and use sit in your lexical actions.
+   */
+  public static Token newToken(int ofKind, String image)
+  {
+    switch(ofKind)
+    {
+      default : return new Token(ofKind, image);
+    }
+  }
+
+  public static Token newToken(int ofKind)
+  {
+    return newToken(ofKind, null);
+  }
+
+}
+/* JavaCC - OriginalChecksum=58572f92492741f9077f0f848faf8c04 (do not edit this line) */

+ 146 - 0
saga-kotlin-database/src/main/kotlin/com/sybotan/database/parser/TokenMgrError.java

@@ -0,0 +1,146 @@
+/* Generated By:JavaCC: Do not edit this line. TokenMgrError.java Version 6.1 */
+/* JavaCCOptions: */
+package com.sybotan.database.parser;
+
+/** Token Manager Error. */
+public class TokenMgrError extends Error
+{
+
+  /**
+   * The version identifier for this Serializable class.
+   * Increment only if the <i>serialized</i> form of the
+   * class changes.
+   */
+  private static final long serialVersionUID = 1L;
+
+  /*
+   * Ordinals for various reasons why an Error of this type can be thrown.
+   */
+
+  /**
+   * Lexical error occurred.
+   */
+  public static final int LEXICAL_ERROR = 0;
+
+  /**
+   * An attempt was made to create a second instance of a static token manager.
+   */
+  public static final int STATIC_LEXER_ERROR = 1;
+
+  /**
+   * Tried to change to an invalid lexical state.
+   */
+  public static final int INVALID_LEXICAL_STATE = 2;
+
+  /**
+   * Detected (and bailed out of) an infinite loop in the token manager.
+   */
+  public static final int LOOP_DETECTED = 3;
+
+  /**
+   * Indicates the reason why the exception is thrown. It will have
+   * one of the above 4 values.
+   */
+  int errorCode;
+
+  /**
+   * Replaces unprintable characters by their escaped (or unicode escaped)
+   * equivalents in the given string
+   */
+  protected static final String addEscapes(String str) {
+    StringBuffer retval = new StringBuffer();
+    char ch;
+    for (int i = 0; i < str.length(); i++) {
+      switch (str.charAt(i))
+      {
+        case '\b':
+          retval.append("\\b");
+          continue;
+        case '\t':
+          retval.append("\\t");
+          continue;
+        case '\n':
+          retval.append("\\n");
+          continue;
+        case '\f':
+          retval.append("\\f");
+          continue;
+        case '\r':
+          retval.append("\\r");
+          continue;
+        case '\"':
+          retval.append("\\\"");
+          continue;
+        case '\'':
+          retval.append("\\\'");
+          continue;
+        case '\\':
+          retval.append("\\\\");
+          continue;
+        default:
+          if ((ch = str.charAt(i)) < 0x20 || ch > 0x7e) {
+            String s = "0000" + Integer.toString(ch, 16);
+            retval.append("\\u" + s.substring(s.length() - 4, s.length()));
+          } else {
+            retval.append(ch);
+          }
+          continue;
+      }
+    }
+    return retval.toString();
+  }
+
+  /**
+   * Returns a detailed message for the Error when it is thrown by the
+   * token manager to indicate a lexical error.
+   * Parameters :
+   *    EOFSeen     : indicates if EOF caused the lexical error
+   *    curLexState : lexical state in which this error occurred
+   *    errorLine   : line number when the error occurred
+   *    errorColumn : column number when the error occurred
+   *    errorAfter  : prefix that was seen before this error occurred
+   *    curchar     : the offending character
+   * Note: You can customize the lexical error message by modifying this method.
+   */
+  protected static String LexicalErr(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, int curChar) {
+    char curChar1 = (char)curChar;
+    return("Lexical error at line " +
+          errorLine + ", column " +
+          errorColumn + ".  Encountered: " +
+          (EOFSeen ? "<EOF> " : ("\"" + addEscapes(String.valueOf(curChar1)) + "\"") + " (" + (int)curChar + "), ") +
+          "after : \"" + addEscapes(errorAfter) + "\"");
+  }
+
+  /**
+   * You can also modify the body of this method to customize your error messages.
+   * For example, cases like LOOP_DETECTED and INVALID_LEXICAL_STATE are not
+   * of end-users concern, so you can return something like :
+   *
+   *     "Internal Error : Please file a bug report .... "
+   *
+   * from this method for such cases in the release version of your parser.
+   */
+  public String getMessage() {
+    return super.getMessage();
+  }
+
+  /*
+   * Constructors of various flavors follow.
+   */
+
+  /** No arg constructor. */
+  public TokenMgrError() {
+  }
+
+  /** Constructor with message and reason. */
+  public TokenMgrError(String message, int reason) {
+    super(message);
+    errorCode = reason;
+  }
+
+  /** Full Constructor. */
+  public TokenMgrError(boolean EOFSeen, int lexState, int errorLine, int errorColumn, String errorAfter, int curChar, int reason) {
+    this(LexicalErr(EOFSeen, lexState, errorLine, errorColumn, errorAfter, curChar), reason);
+  }
+}
+/* JavaCC - OriginalChecksum=f7fe7ad355589d06f1cab51c9cfb6580 (do not edit this line) */

+ 3 - 3
saga-kotlin-mybatis/build.gradle

@@ -62,8 +62,8 @@ dependencies {
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // Sybotan依赖
-    implementation project(':sybotan-kotlin-base')
-    implementation project(':sybotan-kotlin-database')
+    implementation project(':saga-kotlin-base')
+    implementation project(':saga-kotlin-database')
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -105,7 +105,7 @@ uploadArchives {
             pom.project {
                 name project.name
                 packaging "jar"
-                url SYBOTAN_URL
+                url SAGA_URL
                 description "斯伯坦机器人 Kotlin 数据库操作支持库。"
                 licenses {
                     license {

+ 2 - 0
saga-kotlin-mybatis/src/main/kotlin/com/sybotan/mybatis/IBaseMapper.kt

@@ -121,6 +121,7 @@ interface IBaseMapper<ENTITY: Any> {
      * @param   id1         对象表ID字段名
      * @param   id2         级联对象ID字段名
      * @param   self        自身级联
+     * @param   filter      附加过滤条件
      * @param   idList      对象ID列表
      * @return  关系列表
      */
@@ -129,6 +130,7 @@ interface IBaseMapper<ENTITY: Any> {
                       @Param("id1")id1: String,
                       @Param("id2")id2: String,
                       @Param("self")self: Boolean,
+                      @Param("filter")filter: String,
                       @Param("idList")idList: ArrayList<Any>,
                       @Param("whereArgs")whereArgs: Map<String, Any>): ArrayList<HashMap<String, Any>>
 } // Interface IBaseMapper

+ 3 - 2
saga-kotlin-mybatis/src/main/kotlin/com/sybotan/mybatis/SAbstractMybatisDao.kt

@@ -199,10 +199,11 @@ abstract class SAbstractMybatisDao<ENTITY: Any>(entityClazz: Class<ENTITY>) : SA
      * @param   id1         对象表ID字段名
      * @param   id2         级联对象ID字段名
      * @param   self        自身级联
+     * @param   filter      附加过滤条件
      * @param   idList      对象ID列表
      * @return  关系列表
      */
-    override fun relationQuery(table: String, id1: String, id2: String, self: Boolean, idList: ArrayList<Any>): ArrayList<HashMap<String, Any>> {
-        return mapper.relationQuery(table, id1, id2, self, idList, HashMap());
+    override fun relationQuery(table: String, id1: String, id2: String, self: Boolean, filter: String, idList: ArrayList<Any>): ArrayList<HashMap<String, Any>> {
+        return mapper.relationQuery(table, id1, id2, self, filter, idList, HashMap());
     } // Fun cascadeIdList()
 } // Class SAbstractMybatisDao

+ 7 - 0
saga-kotlin-mybatis/src/main/kotlin/com/sybotan/mybatis/SSqlProvider.kt

@@ -303,6 +303,7 @@ open class SSqlProvider {
         val id1 = argsMap["id1"] as String
         val id2 = argsMap["id2"] as String
         val self = argsMap["self"] as Boolean
+        val filter = argsMap["filter"] as String
         val idList = argsMap["idList"] as ArrayList<Any>
         val whereArgs = argsMap["whereArgs"] as HashMap<String, Any>
 
@@ -319,6 +320,9 @@ open class SSqlProvider {
                     builder.append("#{whereArgs.args_$index}")
                     whereArgs["args_$index"] = item
                 }
+                if (filter != "") {
+                    WHERE(filter)
+                }
                 WHERE("${driver.escName(id1)} IN (${builder.toString()})")
             }
         }.toString()
@@ -338,6 +342,9 @@ open class SSqlProvider {
                         builder.append("#{whereArgs.args_$index}")
                         whereArgs["args_$index"] = item
                     }
+                    if (filter != "") {
+                        WHERE(filter)
+                    }
                     WHERE("${driver.escName(id2)} IN (${builder.toString()})")
                 }
             }.toString()

+ 4 - 4
saga-kotlin-mysql/build.gradle

@@ -66,9 +66,9 @@ dependencies {
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // Sybotan依赖
-    compile project(':sybotan-kotlin-base')
-    compile project(':sybotan-kotlin-database')
-    compile project(':sybotan-kotlin-mybatis')
+    compile project(':saga-kotlin-base')
+    compile project(':saga-kotlin-database')
+    compile project(':saga-kotlin-mybatis')
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -110,7 +110,7 @@ uploadArchives {
             pom.project {
                 name project.name
                 packaging "jar"
-                url SYBOTAN_URL
+                url SAGA_URL
                 description "斯伯坦机器人 Kotlin MySQL数据库操作支持库。"
                 licenses {
                     license {

+ 4 - 4
saga-kotlin-postgresql/build.gradle

@@ -66,9 +66,9 @@ dependencies {
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // Sybotan依赖
-    compile project(':sybotan-kotlin-base')
-    compile project(':sybotan-kotlin-database')
-    compile project(':sybotan-kotlin-mybatis')
+    compile project(':saga-kotlin-base')
+    compile project(':saga-kotlin-database')
+    compile project(':saga-kotlin-mybatis')
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -110,7 +110,7 @@ uploadArchives {
             pom.project {
                 name project.name
                 packaging "jar"
-                url SYBOTAN_URL
+                url SAGA_URL
                 description "斯伯坦机器人 Kotlin PostgreSQL数据库操作支持库。"
                 licenses {
                     license {