org.mongojx.fluent.core.MongoJxParser.java Source code

Java tutorial

Introduction

Here is the source code for org.mongojx.fluent.core.MongoJxParser.java

Source

/*
 *
 *  * Copyright (c) 2015 Ivan Hristov <hristov[DOT]iv[AT]gmail[DOT]com>
 *  *
 *  * Licensed under the Apache License, Version 2.0 (the "License");
 *  * you may not use this file except in compliance with the License.
 *  * You may obtain a copy of the License at
 *  *
 *  *    http://www.apache.org/licenses/LICENSE-2.0
 *  *
 *  * Unless required by applicable law or agreed to in writing, software
 *  * distributed under the License is distributed on an "AS IS" BASIS,
 *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  * See the License for the specific language governing permissions and
 *  * limitations under the License.
 *
 */

package org.mongojx.fluent.core;

import org.apache.commons.lang3.math.NumberUtils;
import org.bson.Document;

import java.util.ArrayList;
import java.util.List;

import static org.mongojx.fluent.core.ParsingEvent.*;

public class MongoJxParser {

    public static QueryTuple bind(String filter, Object... parameters) {
        ParsingEvent state = null;
        int keyStartIndex = 0;
        int keyStopIndex = 0;
        int valueStartIndex = 0;
        int parameterIndex = 0;
        Document finalDocument = new Document();
        Document document = finalDocument;
        int depth = 0;
        int arrays = 1;
        List<Document> documents = new ArrayList();

        for (int i = 0; i < filter.length(); i++) {
            char character = filter.charAt(i);
            if (isJsonObjectStarting(character)) {
                if (state == KEY_VALUE_DELIMITER) {
                    Document nestedDocument = new Document();
                    document.put(filter.substring(keyStartIndex, keyStopIndex), nestedDocument);
                    document = nestedDocument;
                } else if (state == IN_ARRAY_AND_SEPARATOR) {
                    document = new Document();
                    finalDocument = document;
                }
                state = START_OBJECT;
                keyStartIndex = i + 1;
                depth++;
            } else if (isDoubleStringCharacter(character)) {
                if (isDoubleStringEnding(state)) {
                    state = END_DOUBLE_QUOTE_STRING;
                    document.put(filter.substring(keyStartIndex, keyStopIndex),
                            filter.substring(valueStartIndex, i));
                } else {
                    valueStartIndex = i + 1;
                    state = START_DOUBLE_QUOTE_STRING;
                }
            } else if (isSingleStringCharacter(character)) {
                if (isSingleStringEnding(state)) {
                    state = END_SINGLE_QUOTE_STRING;
                } else if (isSingleStringStarting(state)) {
                    keyStartIndex = i;
                    state = START_SINGLE_QUOTE_STRING;
                }
            } else if (isJsonObjectEnding(character)) {
                depth--;
                if (depth == 0) {
                    documents.add(finalDocument);
                    state = END_OF_IN_ARRAY_OBJECT;
                }
            } else if (isArrayStarting(character)) {
                arrays--;
                if (arrays == 0) {
                    return new QueryTuple(i + 1, documents);
                }
            } else if (isArrayEnding(character)) {
                QueryTuple queryTuple = bind(filter.substring(i + 1), parameters);
                document.put(filter.substring(keyStartIndex, keyStopIndex), queryTuple.getDocuments());
                i = i + queryTuple.getIndex();
            } else if (isKeyValueSeparator(character)) {
                if (state != KEY_END) {
                    keyStopIndex = i;
                }
                document.put(filter.substring(keyStartIndex, keyStopIndex), "");
                state = KEY_VALUE_DELIMITER;
            } else if (isParameter(character)) {
                state = PARAMETER;
                document.put(filter.substring(keyStartIndex, keyStopIndex), parameters[parameterIndex]);
                parameterIndex++;
            } else if (isSeparator(character)) {
                keyStartIndex = i + 1;
                if (state == END_OF_IN_ARRAY_OBJECT) {
                    state = IN_ARRAY_AND_SEPARATOR;
                } else {
                    state = AND_SEPARATOR;
                }
            } else if (Character.isWhitespace(character)) {
                if (state == AND_SEPARATOR) {
                    keyStartIndex = i + 1;
                } else if (state == START_OBJECT) {
                    keyStartIndex = i + 1;
                } else if (state == START_INLINE_NUMERIC_VALUE) {
                    state = END_INLINE_NUMERIC_VALUE;
                    String value = filter.substring(valueStartIndex, i);
                    document.put(filter.substring(keyStartIndex, keyStopIndex), NumberUtils.createNumber(value));
                } else if (state == KEY_START) {
                    keyStopIndex = i;
                    state = KEY_END;
                }
            } else if (Character.isDigit(character) && state == KEY_VALUE_DELIMITER) {
                state = START_INLINE_NUMERIC_VALUE;
                valueStartIndex = i;
            } else if (Character.isAlphabetic(character) && (state == AND_SEPARATOR || state == START_OBJECT)) {
                state = KEY_START;
            }

        }

        return new QueryTuple(filter.length(), documents);
    }

    private static boolean isSeparator(char character) {
        return character == ',';
    }

    private static boolean isParameter(char character) {
        return character == '#';
    }

    private static boolean isKeyValueSeparator(char character) {
        return character == ':';
    }

    private static boolean isArrayEnding(char character) {
        return character == '[';
    }

    private static boolean isArrayStarting(char character) {
        return character == ']';
    }

    private static boolean isDoubleStringEnding(ParsingEvent state) {
        return state == START_DOUBLE_QUOTE_STRING;
    }

    private static boolean isSingleStringStarting(ParsingEvent state) {
        return state != START_DOUBLE_QUOTE_STRING;
    }

    private static boolean isSingleStringEnding(ParsingEvent state) {
        return state == START_SINGLE_QUOTE_STRING;
    }

    private static boolean isSingleStringCharacter(char character) {
        return character == '\'';
    }

    private static boolean isDoubleStringCharacter(char character) {
        return character == '\"';
    }

    private static boolean isJsonObjectStarting(char character) {
        return character == '{';
    }

    private static boolean isJsonObjectEnding(char character) {
        return character == '}';
    }
}