private static JsonArray deserialize()

in tooling/camel-util-json/src/main/java/org/apache/camel/util/json/Jsoner.java [154:376]


    private static JsonArray deserialize(final Reader deserializable, final Set<DeserializationOptions> flags)
            throws DeserializationException, IOException {
        final Yylex lexer = new Yylex(deserializable);
        Yytoken token;
        States currentState;
        int returnCount = 1;
        final LinkedList<States> stateStack = new LinkedList<>();
        final LinkedList<Object> valueStack = new LinkedList<>();
        stateStack.addLast(States.INITIAL);
        do {
            /* Parse through the parsable string's tokens. */
            currentState = Jsoner.popNextState(stateStack);
            token = Jsoner.lexNextToken(lexer);
            switch (currentState) {
                case DONE:
                    /* The parse has finished a JSON value. */
                    if (!flags.contains(DeserializationOptions.ALLOW_CONCATENATED_JSON_VALUES)
                            || Yytoken.Types.END.equals(token.getType())) {
                        /*
                         * Break if concatenated values are not allowed or if an END
                         * token is read.
                         */
                        break;
                    }
                    /*
                     * Increment the amount of returned JSON values and treat the
                     * token as if it were a fresh parse.
                     */
                    returnCount += 1;
                    /* Fall through to the case for the initial state. */
                    //$FALL-THROUGH$
                case INITIAL:
                    /* The parse has just started. */
                    switch (token.getType()) {
                        case DATUM:
                            /* A boolean, null, Number, or String could be detected. */
                            if (flags.contains(DeserializationOptions.ALLOW_JSON_DATA)) {
                                valueStack.addLast(token.getValue());
                                stateStack.addLast(States.DONE);
                            } else {
                                throw new DeserializationException(
                                        lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token);
                            }
                            break;
                        case LEFT_BRACE:
                            /* An object is detected. */
                            if (flags.contains(DeserializationOptions.ALLOW_JSON_OBJECTS)) {
                                valueStack.addLast(new JsonObject());
                                stateStack.addLast(States.PARSING_OBJECT);
                            } else {
                                throw new DeserializationException(
                                        lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token);
                            }
                            break;
                        case LEFT_SQUARE:
                            /* An array is detected. */
                            if (flags.contains(DeserializationOptions.ALLOW_JSON_ARRAYS)) {
                                valueStack.addLast(new JsonArray());
                                stateStack.addLast(States.PARSING_ARRAY);
                            } else {
                                throw new DeserializationException(
                                        lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token);
                            }
                            break;
                        default:
                            /* Neither a JSON array or object was detected. */
                            throw new DeserializationException(
                                    lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
                    }
                    break;
                case PARSED_ERROR:
                    /*
                     * The parse could be in this state due to the state stack not
                     * having a state to pop off.
                     */
                    throw new DeserializationException(
                            lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
                case PARSING_ARRAY:
                    switch (token.getType()) {
                        case COMMA:
                            /*
                             * The parse could detect a comma while parsing an array
                             * since it separates each element.
                             */
                            stateStack.addLast(currentState);
                            break;
                        case DATUM:
                            /* The parse found an element of the array. */
                            JsonArray val = (JsonArray) valueStack.getLast();
                            val.add(token.getValue());
                            stateStack.addLast(currentState);
                            break;
                        case LEFT_BRACE:
                            /* The parse found an object in the array. */
                            val = (JsonArray) valueStack.getLast();
                            final JsonObject object = new JsonObject();
                            val.add(object);
                            valueStack.addLast(object);
                            stateStack.addLast(currentState);
                            stateStack.addLast(States.PARSING_OBJECT);
                            break;
                        case LEFT_SQUARE:
                            /* The parse found another array in the array. */
                            val = (JsonArray) valueStack.getLast();
                            final JsonArray array = new JsonArray();
                            val.add(array);
                            valueStack.addLast(array);
                            stateStack.addLast(currentState);
                            stateStack.addLast(States.PARSING_ARRAY);
                            break;
                        case RIGHT_SQUARE:
                            /* The parse found the end of the array. */
                            if (valueStack.size() > returnCount) {
                                valueStack.removeLast();
                            } else {
                                /* The parse has been fully resolved. */
                                stateStack.addLast(States.DONE);
                            }
                            break;
                        default:
                            /* Any other token is invalid in an array. */
                            throw new DeserializationException(
                                    lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
                    }
                    break;
                case PARSING_OBJECT:
                    /* The parse has detected the start of an object. */
                    switch (token.getType()) {
                        case COMMA:
                            /*
                             * The parse could detect a comma while parsing an object
                             * since it separates each key value pair. Continue parsing
                             * the object.
                             */
                            stateStack.addLast(currentState);
                            break;
                        case DATUM:
                            /* The token ought to be a key. */
                            if (token.getValue() instanceof String) {
                                /*
                                 * JSON keys are always strings, strings are not always
                                 * JSON keys but it is going to be treated as one.
                                 * Continue parsing the object.
                                 */
                                final String key = (String) token.getValue();
                                valueStack.addLast(key);
                                stateStack.addLast(currentState);
                                stateStack.addLast(States.PARSING_ENTRY);
                            } else {
                                /*
                                 * Abort! JSON keys are always strings and it wasn't a
                                 * string.
                                 */
                                throw new DeserializationException(
                                        lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
                            }
                            break;
                        case RIGHT_BRACE:
                            /* The parse has found the end of the object. */
                            if (valueStack.size() > returnCount) {
                                /* There are unresolved values remaining. */
                                valueStack.removeLast();
                            } else {
                                /* The parse has been fully resolved. */
                                stateStack.addLast(States.DONE);
                            }
                            break;
                        default:
                            /* The parse didn't detect the end of an object or a key. */
                            throw new DeserializationException(
                                    lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
                    }
                    break;
                case PARSING_ENTRY:
                    switch (token.getType()) {
                        /* Parsed pair keys can only happen while parsing objects. */
                        case COLON:
                            /*
                             * The parse could detect a colon while parsing a key value
                             * pair since it separates the key and value from each
                             * other. Continue parsing the entry.
                             */
                            stateStack.addLast(currentState);
                            break;
                        case DATUM:
                            /* The parse has found a value for the parsed pair key. */
                            String key = (String) valueStack.removeLast();
                            JsonObject parent = (JsonObject) valueStack.getLast();
                            parent.put(key, token.getValue());
                            break;
                        case LEFT_BRACE:
                            /* The parse has found an object for the parsed pair key. */
                            key = (String) valueStack.removeLast();
                            parent = (JsonObject) valueStack.getLast();
                            final JsonObject object = new JsonObject();
                            parent.put(key, object);
                            valueStack.addLast(object);
                            stateStack.addLast(States.PARSING_OBJECT);
                            break;
                        case LEFT_SQUARE:
                            /* The parse has found an array for the parsed pair key. */
                            key = (String) valueStack.removeLast();
                            parent = (JsonObject) valueStack.getLast();
                            final JsonArray array = new JsonArray();
                            parent.put(key, array);
                            valueStack.addLast(array);
                            stateStack.addLast(States.PARSING_ARRAY);
                            break;
                        default:
                            /*
                             * The parse didn't find anything for the parsed pair key.
                             */
                            throw new DeserializationException(
                                    lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
                    }
                    break;
                default:
                    break;
            }
            /* If we're not at the END and DONE then do the above again. */
        } while (!(States.DONE.equals(currentState) && Yytoken.Types.END.equals(token.getType())));
        return new JsonArray(valueStack);
    }