OSDN Git Service

removed all files
[xerial/xerial-core.git] / src / main / java / org / xerial / silk / SilkParser.java
diff --git a/src/main/java/org/xerial/silk/SilkParser.java b/src/main/java/org/xerial/silk/SilkParser.java
deleted file mode 100755 (executable)
index a016ffa..0000000
+++ /dev/null
@@ -1,940 +0,0 @@
-/*--------------------------------------------------------------------------\r
- *  Copyright 2009 Taro L. Saito\r
- *\r
- *  Licensed under the Apache License, Version 2.0 (the "License");\r
- *  you may not use this file except in compliance with the License.\r
- *  You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- *  Unless required by applicable law or agreed to in writing, software\r
- *  distributed under the License is distributed on an "AS IS" BASIS,\r
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- *  See the License for the specific language governing permissions and\r
- *  limitations under the License.\r
- *--------------------------------------------------------------------------*/\r
-//--------------------------------------\r
-// XerialJ\r
-//\r
-// SilkParser.java\r
-// Since: Jun 1, 2009 2:45:39 PM\r
-//\r
-// $URL: http://www.xerial.org/svn/project/XerialJ/trunk/xerial-core/src/main/java/org/xerial/silk/SilkParser.java $\r
-// $Author: leo $\r
-//--------------------------------------\r
-package org.xerial.silk;\r
-\r
-import java.io.IOException;\r
-import java.io.InputStreamReader;\r
-import java.io.Reader;\r
-import java.lang.reflect.Field;\r
-import java.net.URL;\r
-import java.util.ArrayList;\r
-import java.util.Collections;\r
-import java.util.Comparator;\r
-import java.util.HashMap;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.TreeMap;\r
-import java.util.regex.Pattern;\r
-\r
-import org.xerial.core.XerialErrorCode;\r
-import org.xerial.core.XerialException;\r
-import org.xerial.json.JSONArray;\r
-import org.xerial.json.JSONEvent;\r
-import org.xerial.json.JSONException;\r
-import org.xerial.json.JSONObject;\r
-import org.xerial.json.JSONPullParser;\r
-import org.xerial.json.JSONUtil;\r
-import org.xerial.json.JSONValue;\r
-import org.xerial.json.JSONValueType;\r
-import org.xerial.silk.impl.SilkDataLine;\r
-import org.xerial.silk.impl.SilkFunction;\r
-import org.xerial.silk.impl.SilkFunctionArg;\r
-import org.xerial.silk.impl.SilkJSONValue;\r
-import org.xerial.silk.impl.SilkNode;\r
-import org.xerial.silk.impl.SilkNodeOccurrence;\r
-import org.xerial.silk.impl.SilkValue;\r
-import org.xerial.silk.plugin.SilkFunctionArgument;\r
-import org.xerial.silk.plugin.SilkFunctionPlugin;\r
-import org.xerial.util.FileResource;\r
-import org.xerial.util.StringUtil;\r
-import org.xerial.util.bean.TypeInfo;\r
-import org.xerial.util.log.Logger;\r
-import org.xerial.util.reflect.ReflectionUtil;\r
-import org.xerial.util.tree.TreeEventHandler;\r
-import org.xerial.util.tree.TreeParser;\r
-import org.xerial.util.xml.impl.TreeEventQueue;\r
-\r
-/**\r
- * Push-style Silk format parser\r
- * \r
- * @author leo\r
- * \r
- */\r
-public class SilkParser implements SilkEventHandler, TreeParser {\r
-    private static Logger _logger = Logger.getLogger(SilkParser.class);\r
-\r
-    private final SilkLineParser parser;\r
-    private final SilkEnv parseContext;\r
-    private final SilkParserConfig config;\r
-\r
-    private TreeEventQueue eventQueue = new TreeEventQueue();\r
-    private long numReadLine = 0;\r
-\r
-    /**\r
-     * Creates a new reader with the specified reader\r
-     * \r
-     * @param input\r
-     * @throws IOException\r
-     */\r
-    public SilkParser(Reader input) throws IOException {\r
-        this(input, SilkEnv.newEnv());\r
-    }\r
-\r
-    /**\r
-     * Creates a new reader inherited the given environment\r
-     * \r
-     * @param input\r
-     * @param env\r
-     * @throws IOException\r
-     */\r
-    public SilkParser(Reader input, SilkEnv env) throws IOException {\r
-        this(input, env, new SilkParserConfig());\r
-    }\r
-\r
-    /**\r
-     * Create a new reader for reading the specified resource URL\r
-     * \r
-     * @param resourcePath\r
-     * @throws IOException\r
-     */\r
-    public SilkParser(URL resourcePath) throws IOException {\r
-        this(resourcePath, SilkEnv.newEnv());\r
-    }\r
-\r
-    public SilkParser(URL resourcePath, SilkParserConfig config) throws IOException {\r
-        this(resourcePath, SilkEnv.newEnv(), config);\r
-    }\r
-\r
-    public SilkParser(URL resource, SilkEnv env) throws IOException {\r
-        this(resource, env, new SilkParserConfig());\r
-    }\r
-\r
-    public SilkParser(URL resource, SilkEnv env, SilkParserConfig config) throws IOException {\r
-        this(new InputStreamReader(resource.openStream()), SilkEnv.newEnv(env,\r
-                getResourceBasePath(resource)), config);\r
-    }\r
-\r
-    public SilkParser(Reader input, SilkEnv env, SilkParserConfig config) throws IOException {\r
-        this.config = config;\r
-        if (config.numWorkers > 1)\r
-            this.parser = new SilkLineFastParser(input);\r
-        else\r
-            this.parser = new SilkLinePushParser(input);\r
-        this.parseContext = env;\r
-    }\r
-\r
-    static String getResourceBasePath(URL resource) {\r
-        String path = resource.toExternalForm();\r
-        int fileNamePos = path.lastIndexOf("/");\r
-        String resourceBasePath = fileNamePos > 0 ? path.substring(0, fileNamePos) : null;\r
-        return resourceBasePath;\r
-    }\r
-\r
-    /**\r
-     * Concatenates the base path and the resource name\r
-     * \r
-     * @param resourceBasePath\r
-     * @param resourceName\r
-     * @return\r
-     */\r
-    static String getResourcePath(String resourceBasePath, String resourceName) {\r
-        String resourcePath = resourceBasePath;\r
-        if (!resourcePath.endsWith("/"))\r
-            resourcePath += "/";\r
-        resourcePath += resourceName;\r
-        return resourcePath;\r
-    }\r
-\r
-    TreeEventHandler handler;\r
-\r
-    public void parse(TreeEventHandler handler) throws Exception {\r
-        this.handler = handler;\r
-\r
-        handler.init();\r
-        parser.parse(this);\r
-        closeContextUpTo(parseContext.getIndentationOffset());\r
-\r
-        handler.finish();\r
-    }\r
-\r
-    public void parseWithoutInitAndFinish(TreeEventHandler handler) throws Exception {\r
-        this.handler = handler;\r
-\r
-        parser.parse(this);\r
-        closeContextUpTo(parseContext.getIndentationOffset());\r
-    }\r
-\r
-    public void handle(SilkEvent event) throws Exception {\r
-        try {\r
-            switch (event.getType()) {\r
-            case DATA_LINE:\r
-                parseDataLine(event);\r
-                break;\r
-            case NODE:\r
-                SilkNode newContextNode = SilkNode.class.cast(event.getElement());\r
-                openContext(newContextNode);\r
-                break;\r
-            case FUNCTION:\r
-                SilkFunction function = SilkFunction.class.cast(event.getElement());\r
-                evalFunction(function);\r
-                break;\r
-            case MULTILINE_ENTRY_SEPARATOR: // ==\r
-            {\r
-                SilkContext context = parseContext.peekLastContext();\r
-                SilkNode schema = context.contextNode;\r
-                if (parseContext.isAttributeOpen) {\r
-                    SilkNode attributeNode = schema.getChildNodes().get(\r
-                            parseContext.contextNodeAttributeCursor);\r
-                    leave(attributeNode.getName());\r
-                }\r
-                leave(schema.getName());\r
-                // reset\r
-                parseContext.contextNodeAttributeCursor = 0;\r
-                parseContext.isAttributeOpen = false;\r
-                break;\r
-            }\r
-            case MULTILINE_SEPARATOR: {\r
-                SilkContext context = parseContext.peekLastContext();\r
-                SilkNode schema = context.contextNode;\r
-                if (parseContext.isAttributeOpen) {\r
-                    SilkNode attributeNode = schema.getChildNodes().get(\r
-                            parseContext.contextNodeAttributeCursor);\r
-                    leave(attributeNode.getName());\r
-                }\r
-                parseContext.contextNodeAttributeCursor++;\r
-                parseContext.isAttributeOpen = false;\r
-                break;\r
-            }\r
-            case BLANK_LINE:\r
-                break;\r
-            case END_OF_FILE:\r
-                break;\r
-            case PREAMBLE:\r
-                break;\r
-            case COMMENT_LINE:\r
-                break;\r
-            case UNKNOWN:\r
-            default:\r
-                _logger.warn(String.format("unknown event type (line=%d): %s", numReadLine, event));\r
-                break;\r
-            }\r
-        }\r
-        catch (XerialException e) {\r
-            // When finding the parse error, only report warning message with the line number\r
-            if (e.getErrorCode() == XerialErrorCode.PARSE_ERROR)\r
-                _logger.warn(String.format("parse error at line=%d: %s", numReadLine, e));\r
-            else\r
-                throw e;\r
-\r
-        }\r
-\r
-        numReadLine++;\r
-    }\r
-\r
-    private static final Pattern tabSplit = Pattern.compile("\t");\r
-    private static final Pattern commaSplit = Pattern.compile(",");\r
-\r
-    private void parseDataLine(SilkEvent currentEvent) throws Exception {\r
-        // pop the context stack until finding a node for stream data node occurrence\r
-        while (!parseContext.isContextNodeStackEmpty()) {\r
-            SilkContext context = parseContext.peekLastContext();\r
-            SilkNode node = context.contextNode;\r
-            if (!node.getOccurrence().isFollowedByStreamData()) {\r
-                parseContext.popLastContext();\r
-                if (context.isOpen)\r
-                    leave(node.getName());\r
-            }\r
-            else\r
-                break;\r
-        }\r
-\r
-        if (parseContext.isContextNodeStackEmpty()) {\r
-            // use default column names(c1, c2, ...) \r
-            SilkDataLine line = SilkDataLine.class.cast(currentEvent.getElement());\r
-            String[] columns = tabSplit.split(line.getTrimmedDataLine(), 0);\r
-            int index = 1;\r
-            visit("row", null);\r
-            for (String each : columns) {\r
-                String columnName = String.format("c%d", index++);\r
-\r
-                // TODO use evalColumnData\r
-                visit(columnName, each);\r
-                leave(columnName);\r
-            }\r
-            leave("row");\r
-        }\r
-        else {\r
-            SilkContext context = parseContext.peekLastContext();\r
-            SilkNode schema = context.contextNode;\r
-            SilkDataLine line = SilkDataLine.class.cast(currentEvent.getElement());\r
-            switch (schema.getOccurrence()) {\r
-            case SEQUENCE:\r
-                text(line.getTrimmedDataLine());\r
-                break;\r
-            case SEQUENCE_WITH_NEWLINE:\r
-                text(line.getDataLine() + StringUtil.NEW_LINE);\r
-                break;\r
-            case ZERO_OR_MORE:\r
-                // CSV data\r
-            {\r
-                evalDatalineColumn(schema, line.getTrimmedDataLine());\r
-            }\r
-                break;\r
-            case TABBED_SEQUENCE: {\r
-                String[] columns = tabSplit.split(line.getTrimmedDataLine(), 0);\r
-\r
-                int columnIndex = 0;\r
-                visit(schema.getName(), schema.hasValue() ? schema.getValue().toString() : null);\r
-                for (int i = 0; i < schema.getChildNodes().size(); i++) {\r
-                    SilkNode child = schema.getChildNodes().get(i);\r
-                    if (child.hasValue()) {\r
-                        // output the default value for the column \r
-                        evalDatalineColumn(child, child.getValue().toString());\r
-                    }\r
-                    else {\r
-                        if (columnIndex < columns.length) {\r
-                            String columnData = columns[columnIndex++].trim();\r
-                            if (columnData.length() > 0)\r
-                                evalDatalineColumn(child, columnData);\r
-                        }\r
-                    }\r
-                }\r
-                leave(schema.getName());\r
-                break;\r
-            }\r
-            case MULTILINE_SEQUENCE: {\r
-                int cursor = parseContext.contextNodeAttributeCursor;\r
-\r
-                if (cursor >= schema.getChildNodes().size())\r
-                    break;\r
-\r
-                SilkNode attributeNode = schema.getChildNodes().get(cursor);\r
-                if (cursor == 0 && !parseContext.isAttributeOpen) {\r
-                    visit(schema.getName(), schema.hasValue() ? schema.getValue().toString() : null);\r
-                }\r
-                if (!parseContext.isAttributeOpen) {\r
-                    if (attributeNode.hasValue())\r
-                        visit(attributeNode.getName(), attributeNode.getValue().toString());\r
-                    else\r
-                        visit(attributeNode.getName(), null);\r
-\r
-                    parseContext.isAttributeOpen = true;\r
-                }\r
-                text(line.getTrimmedDataLine());\r
-                break;\r
-            }\r
-            }\r
-        }\r
-\r
-    }\r
-\r
-    /**\r
-     * Enqueues a visit event.\r
-     * \r
-     * @param nodeName\r
-     * @param immediateNodeValue\r
-     * @throws Exception\r
-     */\r
-    private void visit(String nodeName, String immediateNodeValue) throws Exception {\r
-        handler.visitNode(nodeName, immediateNodeValue);\r
-\r
-    }\r
-\r
-    /**\r
-     * Enqueues a leave event\r
-     * \r
-     * @param nodeName\r
-     * @throws Exception\r
-     */\r
-    private void leave(String nodeName) throws Exception {\r
-        handler.leaveNode(nodeName);\r
-    }\r
-\r
-    /**\r
-     * Enqueues a text event\r
-     * \r
-     * @param textFragment\r
-     * @throws XerialException\r
-     */\r
-    private void text(String textFragment) throws Exception {\r
-        handler.text(parseContext.getContextNode().getName(), textFragment);\r
-    }\r
-\r
-    /**\r
-     * Closed pre-opened contexts up to the specified indent level\r
-     * \r
-     * @param newIndentLevel\r
-     * @throws Exception\r
-     */\r
-    private void closeContextUpTo(int newIndentLevel) throws Exception {\r
-        while (!parseContext.isContextNodeStackEmpty()) {\r
-            SilkContext context = parseContext.peekLastContext();\r
-            SilkNode node = context.contextNode;\r
-            if (node.getIndentLevel() >= newIndentLevel) {\r
-                parseContext.popLastContext();\r
-\r
-                if (parseContext.isAttributeOpen) {\r
-                    // close attribute \r
-                    SilkNode attribute = node.getChildNodes().get(\r
-                            parseContext.contextNodeAttributeCursor);\r
-                    leave(attribute.getName());\r
-                    leave(node.getName());\r
-                    parseContext.isAttributeOpen = false;\r
-                }\r
-\r
-                if (context.isOpen) {\r
-                    // close context\r
-                    String nodeName = node.getName();\r
-                    leave(nodeName);\r
-                }\r
-            }\r
-            else\r
-                return;\r
-        }\r
-    }\r
-\r
-    /**\r
-     * Opens a new context for the given node\r
-     * \r
-     * @param node\r
-     *            new context node\r
-     * @param visitor\r
-     * @throws Exception\r
-     */\r
-    private void openContext(SilkNode node) throws Exception {\r
-        int indentLevel = node.getIndentLevel();\r
-        if (indentLevel != SilkNode.NO_INDENT)\r
-            indentLevel += parseContext.getIndentationOffset();\r
-\r
-        closeContextUpTo(indentLevel);\r
-        openContext_internal(node);\r
-    }\r
-\r
-    private void openContext_internal(SilkNode node) throws Exception {\r
-        if (node.getName() == null) {\r
-            // no name nodes must hierarchically organize attribute nodes\r
-            for (SilkNode eachChild : node.getChildNodes()) {\r
-                eachChild.setNodeIndent(node.getNodeIndent());\r
-                openContext_internal(eachChild);\r
-            }\r
-            return;\r
-        }\r
-\r
-        SilkContext currentContext = new SilkContext(node, true);\r
-        parseContext.pushContext(currentContext);\r
-\r
-        SilkNodeOccurrence occurrence = node.getOccurrence();\r
-        if (occurrence.isSchemaOnlyNode()) {\r
-            currentContext.isOpen = false;\r
-            // reset the attribute cursor\r
-            parseContext.contextNodeAttributeCursor = 0;\r
-            parseContext.isAttributeOpen = false;\r
-            return; // do not invoke visit events\r
-        }\r
-\r
-        String nodeName = node.getName();\r
-        SilkValue textValue = node.getValue();\r
-\r
-        // process text values attached to the node\r
-        if (textValue != null) {\r
-            // When the text data is JSON, traverses the JSON data \r
-            if (textValue.isJSON()) {\r
-\r
-                SilkJSONValue jsonValue = SilkJSONValue.class.cast(textValue);\r
-                if (jsonValue.isObject()) {\r
-                    visit(nodeName, null);\r
-                    JSONObject jsonObj = new JSONObject(jsonValue.getValue());\r
-                    walkJSONObject(jsonObj);\r
-                }\r
-                else {\r
-                    currentContext.isOpen = false;\r
-                    JSONArray jsonArray = new JSONArray(jsonValue.getValue());\r
-                    walkJSONAray(jsonArray, nodeName);\r
-                }\r
-            }\r
-            else if (textValue.isFunction()) {\r
-                // evaluate the function \r
-                visit(nodeName, null);\r
-                SilkFunction function = SilkFunction.class.cast(textValue);\r
-                evalFunction(function);\r
-\r
-                return;\r
-            }\r
-            else {\r
-                // Simple text value will be reported as it is.\r
-                visit(nodeName, textValue.toString());\r
-            }\r
-        }\r
-        else {\r
-            if (occurrence == SilkNodeOccurrence.ZERO_OR_MORE) {\r
-                // CSV data\r
-                return; // do not invoke visit events\r
-            }\r
-\r
-            // Report a visit event without text value\r
-            visit(nodeName, null);\r
-        }\r
-\r
-        // Traverse attribute nodes having text values. If no text value is specified for these attributes, \r
-        // they are schema elements for the following DATA_LINE. \r
-        for (SilkNode eachChild : node.getChildNodes()) {\r
-            if (eachChild.hasValue()) {\r
-                openContext(eachChild);\r
-            }\r
-        }\r
-\r
-    }\r
-\r
-    /**\r
-     * Evaluate the function\r
-     * \r
-     * @param function\r
-     * @throws Exception\r
-     */\r
-    private void evalFunction(SilkFunction function) throws Exception {\r
-        SilkFunctionPlugin plugin = getPlugin(function.getName());\r
-        if (plugin == null) {\r
-            _logger.error(String.format("plugin %s not found", function.getName()));\r
-            return;\r
-        }\r
-        // fill the function argument to the plugin instance\r
-        populate(plugin, function.getArgumentList());\r
-\r
-        // evaluate the function\r
-        SilkEnv env = parseContext.newEnvFor(function);\r
-        plugin.init(env);\r
-        plugin.eval(env, handler);\r
-    }\r
-\r
-    /**\r
-     * Has finished reading the stream?\r
-     */\r
-    private boolean hasFinished = false;\r
-\r
-    private void walkMicroFormatRoot(SilkNode schemaNode, JSONArray value) throws Exception {\r
-        // e.g., exon(start, name)\r
-\r
-        if (schemaNode.hasManyOccurrences()) {\r
-            if (schemaNode.hasChildren()) {\r
-                // e.g., exon(start, name)*\r
-                // multiple occurrences: [[start, end], [start, end], ... ] \r
-                for (int i = 0; i < value.size(); i++) {\r
-                    JSONArray eachElement = value.getJSONArray(i);\r
-                    if (eachElement == null)\r
-                        continue;\r
-\r
-                    visit(schemaNode.getName(), null);\r
-                    int index = 0;\r
-                    for (SilkNode eachSubSchema : schemaNode.getChildNodes()) {\r
-                        walkMicroFormatElement(eachSubSchema, eachElement.get(index++));\r
-                    }\r
-                    leave(schemaNode.getName());\r
-                }\r
-            }\r
-            else {\r
-                // e.g. QV*: [20, 50, 50]\r
-                for (int i = 0; i < value.size(); i++) {\r
-                    visit(schemaNode.getName(), value.get(i).toString());\r
-                    leave(schemaNode.getName());\r
-                }\r
-            }\r
-        }\r
-        else {\r
-            // [e1, e2, ...]\r
-            visit(schemaNode.getName(), null);\r
-            int index = 0;\r
-            if (schemaNode.getChildNodes().size() != value.size()) {\r
-                throw new XerialException(XerialErrorCode.INVALID_INPUT, String.format(\r
-                        "data format doesn't match: schema=%s, value=%s", schemaNode, value));\r
-            }\r
-            for (SilkNode each : schemaNode.getChildNodes()) {\r
-                walkMicroFormatElement(each, value.get(index++));\r
-            }\r
-            leave(schemaNode.getName());\r
-        }\r
-    }\r
-\r
-    private void walkMicroFormatElement(SilkNode schemaNode, JSONValue value) throws Exception {\r
-        if (schemaNode.hasChildren()) {\r
-            JSONArray array = value.getJSONArray();\r
-            if (array != null)\r
-                walkMicroFormatRoot(schemaNode, array);\r
-            else\r
-                throw new XerialException(XerialErrorCode.INVALID_INPUT, String.format(\r
-                        "data format doesn't match: schema=%s, value=%s", schemaNode, value));\r
-        }\r
-        else {\r
-            visit(schemaNode.getName(), value.toString());\r
-            leave(schemaNode.getName());\r
-        }\r
-    }\r
-\r
-    private void evalDatalineColumn(SilkNode node, String columnData) throws Exception {\r
-        // 7600 lines/sec\r
-\r
-        if (node.hasChildren()) {\r
-            JSONArray array = new JSONArray(columnData);\r
-            walkMicroFormatRoot(node, array);\r
-            return;\r
-        }\r
-\r
-        switch (node.getOccurrence()) {\r
-        case ONE:\r
-            evalColumnData(node, columnData);\r
-            break;\r
-        case ZERO_OR_MORE:\r
-        case ONE_OR_MORE:\r
-            if (columnData.startsWith("[")) {\r
-                // process JSON array\r
-\r
-                // 500,080 nodes/s, 2.49 MB/s\r
-                // 591,824 nodes/s, 2.95 MB/s (when using JSONPullParser.getValueAsText())\r
-                new EvalJSON(columnData).parseJSONArray(node);\r
-\r
-                // 431,197 nodes/s, 2.15 MB/s\r
-                //JSONArray array = new JSONArray(columnData);\r
-                //walkMicroFormatRoot(node, array);\r
-                return;\r
-            }\r
-            else {\r
-                String[] csv = commaSplit.split(columnData, 0);\r
-                for (String each : csv) {\r
-                    String value = each.trim();\r
-                    evalColumnData(node, value);\r
-                }\r
-                return;\r
-            }\r
-        default:\r
-            evalColumnData(node, columnData);\r
-            return;\r
-        }\r
-\r
-    }\r
-\r
-    private class EvalJSON {\r
-        private final String json;\r
-        private final JSONPullParser parser;\r
-\r
-        EvalJSON(String json) {\r
-            this.json = json;\r
-            this.parser = new JSONPullParser(json);\r
-        }\r
-\r
-        void parseJSONArray(SilkNode schemaNode) throws Exception {\r
-            if (schemaNode.hasManyOccurrences()) {\r
-                JSONEvent e = parser.next();\r
-                if (e != JSONEvent.StartArray)\r
-                    throw new XerialException(XerialErrorCode.PARSE_ERROR, "expected [ but " + e);\r
-\r
-                if (schemaNode.hasChildren()) {\r
-                    // e.g., exon(start, name)*\r
-                    // multiple occurrences: [[start, end], [start, end], ... ]\r
-\r
-                    while ((e = parser.next()) != JSONEvent.EndArray) {\r
-                        JSONValue v = parser.getValue();\r
-                        JSONArray eachElement = v.getJSONArray();\r
-                        if (eachElement == null) {\r
-                            _logger.warn("not an JSONArray: " + v);\r
-                            continue;\r
-                        }\r
-\r
-                        visit(schemaNode.getName(), null);\r
-                        int index = 0;\r
-                        for (SilkNode eachSubSchema : schemaNode.getChildNodes()) {\r
-                            walkMicroFormatElement(eachSubSchema, eachElement.get(index++));\r
-                        }\r
-                        leave(schemaNode.getName());\r
-\r
-                    }\r
-\r
-                }\r
-                else {\r
-                    // e.g. QV*: [20, 50, 50]\r
-                    while ((e = parser.next()) != JSONEvent.EndArray) {\r
-                        visit(schemaNode.getName(), parser.getValueAsText());\r
-                        leave(schemaNode.getName());\r
-                    }\r
-\r
-                }\r
-            }\r
-            else {\r
-\r
-                // [e1, e2, ...]\r
-                visit(schemaNode.getName(), null);\r
-                int index = 0;\r
-\r
-                for (SilkNode each : schemaNode.getChildNodes()) {\r
-                    if (parser.next() == JSONEvent.EndArray) {\r
-                        throw new XerialException(XerialErrorCode.INVALID_INPUT, String.format(\r
-                                "data format doesn't match: schema=%s, value=%s", schemaNode, json));\r
-                    }\r
-\r
-                    walkMicroFormatElement(each, parser.getValue());\r
-                }\r
-                leave(schemaNode.getName());\r
-            }\r
-\r
-        }\r
-\r
-        void parseJSONArrayOf(SilkNode parent) throws XerialException {\r
-            JSONEvent e = parser.next();\r
-            if (e != JSONEvent.StartArray)\r
-                throw new XerialException(XerialErrorCode.PARSE_ERROR, "expected [ but " + e);\r
-\r
-        }\r
-\r
-    }\r
-\r
-    private void evalColumnData(SilkNode node, String columnData) throws Exception {\r
-        try {\r
-            if (node.hasChildren()) {\r
-                // micro-data format\r
-                JSONArray array = new JSONArray(columnData);\r
-                walkMicroFormatRoot(node, array);\r
-                return;\r
-            }\r
-\r
-            String dataType = node.getDataType();\r
-            if (dataType != null && dataType.equalsIgnoreCase("json")) {\r
-                JSONValue json = JSONUtil.parseJSON(columnData);\r
-                if (json.getJSONObject() != null) {\r
-                    if (node.getName().equals("_")) // no name object\r
-                    {\r
-                        walkJSONValue(json, node.getName());\r
-                    }\r
-                    else {\r
-                        visit(node.getName(), null);\r
-                        walkJSONValue(json, node.getName());\r
-                        leave(node.getName());\r
-                    }\r
-                }\r
-                else\r
-                    walkJSONValue(json, node.getName());\r
-            }\r
-            else {\r
-                visit(node.getName(), StringUtil.unquote(columnData));\r
-                leave(node.getName());\r
-            }\r
-        }\r
-        catch (JSONException e) {\r
-            throw new XerialException(e.getErrorCode(), String.format("line=%d: %s", numReadLine, e\r
-                    .getMessage()));\r
-        }\r
-\r
-    }\r
-\r
-    private void walkJSONAray(JSONArray jsonArray, String parentNodeName) throws Exception {\r
-        for (JSONValue each : jsonArray) {\r
-            walkJSONValue(each, parentNodeName);\r
-        }\r
-    }\r
-\r
-    private void walkJSONObject(JSONObject jsonObj) throws Exception {\r
-        for (String key : jsonObj.keys()) {\r
-            JSONValue val = jsonObj.get(key);\r
-            walkJSONValue(val, key);\r
-        }\r
-    }\r
-\r
-    private void walkJSONValue(JSONValue value, String parentNodeName) throws Exception {\r
-        JSONValueType type = value.getValueType();\r
-        switch (type) {\r
-        case Array:\r
-            walkJSONAray(value.getJSONArray(), parentNodeName);\r
-            break;\r
-        case Object:\r
-            walkJSONObject(value.getJSONObject());\r
-            break;\r
-        case Boolean:\r
-            visit(parentNodeName, value.toString());\r
-            leave(parentNodeName);\r
-            break;\r
-        case Double:\r
-            visit(parentNodeName, value.toString());\r
-            leave(parentNodeName);\r
-            break;\r
-        case Integer:\r
-            visit(parentNodeName, value.toString());\r
-            leave(parentNodeName);\r
-            break;\r
-        case Null:\r
-            visit(parentNodeName, value.toString());\r
-            leave(parentNodeName);\r
-            break;\r
-        case String:\r
-            visit(parentNodeName, value.toString());\r
-            leave(parentNodeName);\r
-            break;\r
-        }\r
-\r
-    }\r
-\r
-    /**\r
-     * Plugin holder\r
-     */\r
-    private static Map<String, Class<SilkFunctionPlugin>> pluginTable = null;\r
-\r
-    /**\r
-     * Get the plugin of the specified name\r
-     * \r
-     * @param name\r
-     *            plugin name\r
-     * @return plugin instance or null if no corresponding plugin is found.\r
-     */\r
-    private SilkFunctionPlugin getPlugin(String name) {\r
-        Class<SilkFunctionPlugin> pluginClass = getPluginTable().get(name);\r
-        if (pluginClass == null)\r
-            return null;\r
-\r
-        try {\r
-            SilkFunctionPlugin pluginInstance = pluginClass.newInstance();\r
-            return pluginInstance;\r
-        }\r
-        catch (InstantiationException e) {\r
-            _logger.warn(e);\r
-            return null;\r
-        }\r
-        catch (IllegalAccessException e) {\r
-            _logger.warn(e);\r
-            return null;\r
-        }\r
-    }\r
-\r
-    private Map<String, Class<SilkFunctionPlugin>> getPluginTable() {\r
-        if (pluginTable == null) {\r
-            pluginTable = new TreeMap<String, Class<SilkFunctionPlugin>>();\r
-            // load plugins \r
-            for (Class<SilkFunctionPlugin> each : FileResource.findClasses(SilkFunctionPlugin.class\r
-                    .getPackage(), SilkFunctionPlugin.class, SilkWalker.class.getClassLoader())) {\r
-                String functionName = each.getSimpleName().toLowerCase();\r
-                _logger.trace("loaded " + functionName);\r
-                pluginTable.put(functionName, each);\r
-            }\r
-        }\r
-\r
-        return pluginTable;\r
-    }\r
-\r
-    /**\r
-     * Information of the function (plugin) arguments (\r
-     * {@link SilkFunctionArgument}) described in the Class definition, which\r
-     * implements {@link SilkFunctionPlugin}.\r
-     * \r
-     * @author leo\r
-     * \r
-     */\r
-    private static class PluginField {\r
-        Field field;\r
-        SilkFunctionArgument argInfo;\r
-\r
-        private PluginField(SilkFunctionArgument argInfo, Field field) {\r
-            this.argInfo = argInfo;\r
-            this.field = field;\r
-        }\r
-    }\r
-\r
-    private static class PluginHolder {\r
-        Class< ? extends SilkFunctionPlugin> pluginClass;\r
-        ArrayList<PluginField> argumentFieldList = new ArrayList<PluginField>();\r
-        Map<String, PluginField> keyValueFieldTable = new HashMap<String, PluginField>();\r
-\r
-        public PluginHolder(Class< ? extends SilkFunctionPlugin> pluginClass) {\r
-            this.pluginClass = pluginClass;\r
-\r
-            //ArrayList<SilkFunctionArgument> argDefs = new ArrayList<SilkFunctionArgument>();\r
-            for (Field eachField : pluginClass.getDeclaredFields()) {\r
-                SilkFunctionArgument argInfo = eachField.getAnnotation(SilkFunctionArgument.class);\r
-                if (argInfo != null) {\r
-                    PluginField pf = new PluginField(argInfo, eachField);\r
-                    if (argInfo.name().equals(SilkFunctionArgument.NO_VALUE))\r
-                        argumentFieldList.add(pf);\r
-                    else\r
-                        keyValueFieldTable.put(argInfo.name(), pf);\r
-                }\r
-            }\r
-\r
-            // sort arguments in the order of their ordinal\r
-            Collections.sort(argumentFieldList, new Comparator<PluginField>() {\r
-                public int compare(PluginField o1, PluginField o2) {\r
-                    return o1.argInfo.ordinal() - o2.argInfo.ordinal();\r
-                }\r
-            });\r
-\r
-        }\r
-\r
-        /**\r
-         * Bind function arguments to the plug-in instance\r
-         * \r
-         * @param plugin\r
-         *            the instance of the plug-in\r
-         * @param args\r
-         *            the function arguments\r
-         */\r
-        public void populate(SilkFunctionPlugin plugin, List<SilkFunctionArg> args) {\r
-            int noNameArgCount = 0;\r
-            for (SilkFunctionArg eachArgument : args) {\r
-                String argValue = eachArgument.getValue().toString();\r
-                try {\r
-                    if (eachArgument.hasName()) {\r
-                        // key value arg\r
-                        PluginField f = keyValueFieldTable.get(eachArgument.getName());\r
-                        if (f == null) {\r
-                            _logger.warn("unknown argument: " + eachArgument);\r
-                            continue;\r
-                        }\r
-                        ReflectionUtil.setFieldValue(plugin, f.field, argValue);\r
-                    }\r
-                    else {\r
-                        // unnamed argument\r
-                        // matching argument order\r
-                        if (noNameArgCount >= argumentFieldList.size()) {\r
-                            _logger.warn(String.format(\r
-                                    "no corresponding field for the argument %s is found",\r
-                                    eachArgument));\r
-                            continue;\r
-                        }\r
-                        PluginField f = argumentFieldList.get(noNameArgCount);\r
-                        ReflectionUtil.setFieldValue(plugin, f.field, argValue);\r
-\r
-                        if (!TypeInfo.isCollection(f.field.getType()))\r
-                            noNameArgCount++;\r
-                    }\r
-                }\r
-                catch (XerialException e) {\r
-                    _logger.error(e);\r
-                }\r
-\r
-            }\r
-        }\r
-\r
-    }\r
-\r
-    /**\r
-     * Fill the plug-in argument fields with the given arguments\r
-     * \r
-     * @param plugin\r
-     *            plug-in instance.\r
-     * @param args\r
-     *            function arguments.\r
-     */\r
-    private static void populate(SilkFunctionPlugin plugin, List<SilkFunctionArg> args) {\r
-        PluginHolder holder = new PluginHolder(plugin.getClass());\r
-        holder.populate(plugin, args);\r
-    }\r
-\r
-    public long getNumReadLine() {\r
-        return numReadLine;\r
-    }\r
-}\r