Example #1
0
  /**
   * Stream processing of JSON text.
   *
   * @see ContentHandler
   * @param in
   * @param contentHandler
   * @param isResume - Indicates if it continues previous parsing operation. If set to true, resume
   *     parsing the old stream, and parameter 'in' will be ignored. If this method is called for
   *     the first time in this instance, isResume will be ignored.
   * @throws IOException
   * @throws ParseException
   */
  public void parse(Reader in, ContentHandler contentHandler, boolean isResume)
      throws IOException, ParseException {
    if (!isResume) {
      reset(in);
      handlerStatusStack = new LinkedList();
    } else {
      if (handlerStatusStack == null) {
        isResume = false;
        reset(in);
        handlerStatusStack = new LinkedList();
      }
    }

    LinkedList statusStack = handlerStatusStack;

    try {
      do {
        switch (status) {
          case S_INIT:
            contentHandler.startJSON();
            nextToken();
            switch (token.type) {
              case Yytoken.TYPE_VALUE:
                status = S_IN_FINISHED_VALUE;
                statusStack.addFirst(new Integer(status));
                if (!contentHandler.primitive(token.value)) return;
                break;
              case Yytoken.TYPE_LEFT_BRACE:
                status = S_IN_OBJECT;
                statusStack.addFirst(new Integer(status));
                if (!contentHandler.startObject()) return;
                break;
              case Yytoken.TYPE_LEFT_SQUARE:
                status = S_IN_ARRAY;
                statusStack.addFirst(new Integer(status));
                if (!contentHandler.startArray()) return;
                break;
              default:
                status = S_IN_ERROR; // inner switch
            }
            break;

          case S_IN_FINISHED_VALUE:
            nextToken();
            if (token.type == Yytoken.TYPE_EOF) {
              contentHandler.endJSON();
              status = S_END;
              return;
            } else {
              status = S_IN_ERROR;
              throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
            }

          case S_IN_OBJECT:
            nextToken();
            switch (token.type) {
              case Yytoken.TYPE_COMMA:
                break;
              case Yytoken.TYPE_VALUE:
                if (token.value instanceof String) {
                  String key = (String) token.value;
                  status = S_PASSED_PAIR_KEY;
                  statusStack.addFirst(new Integer(status));
                  if (!contentHandler.startObjectEntry(key)) return;
                } else {
                  status = S_IN_ERROR;
                }
                break;
              case Yytoken.TYPE_RIGHT_BRACE:
                if (statusStack.size() > 1) {
                  statusStack.removeFirst();
                  status = peekStatus(statusStack);
                } else {
                  status = S_IN_FINISHED_VALUE;
                }
                if (!contentHandler.endObject()) return;
                break;
              default:
                status = S_IN_ERROR;
                break; // inner switch
            }
            break;

          case S_PASSED_PAIR_KEY:
            nextToken();
            switch (token.type) {
              case Yytoken.TYPE_COLON:
                break;
              case Yytoken.TYPE_VALUE:
                statusStack.removeFirst();
                status = peekStatus(statusStack);
                if (!contentHandler.primitive(token.value)) return;
                if (!contentHandler.endObjectEntry()) return;
                break;
              case Yytoken.TYPE_LEFT_SQUARE:
                statusStack.removeFirst();
                statusStack.addFirst(new Integer(S_IN_PAIR_VALUE));
                status = S_IN_ARRAY;
                statusStack.addFirst(new Integer(status));
                if (!contentHandler.startArray()) return;
                break;
              case Yytoken.TYPE_LEFT_BRACE:
                statusStack.removeFirst();
                statusStack.addFirst(new Integer(S_IN_PAIR_VALUE));
                status = S_IN_OBJECT;
                statusStack.addFirst(new Integer(status));
                if (!contentHandler.startObject()) return;
                break;
              default:
                status = S_IN_ERROR;
            }
            break;

          case S_IN_PAIR_VALUE:
            statusStack.removeFirst();
            status = peekStatus(statusStack);
            if (!contentHandler.endObjectEntry()) return;
            break;
            /*
             * S_IN_PAIR_VALUE is just a marker to indicate the end of an object entry, it doesn't proccess any token,
             * therefore delay consuming token until next round.
             */

          case S_IN_ARRAY:
            nextToken();
            switch (token.type) {
              case Yytoken.TYPE_COMMA:
                break;
              case Yytoken.TYPE_VALUE:
                if (!contentHandler.primitive(token.value)) return;
                break;
              case Yytoken.TYPE_RIGHT_SQUARE:
                if (statusStack.size() > 1) {
                  statusStack.removeFirst();
                  status = peekStatus(statusStack);
                } else {
                  status = S_IN_FINISHED_VALUE;
                }
                if (!contentHandler.endArray()) return;
                break;
              case Yytoken.TYPE_LEFT_BRACE:
                status = S_IN_OBJECT;
                statusStack.addFirst(new Integer(status));
                if (!contentHandler.startObject()) return;
                break;
              case Yytoken.TYPE_LEFT_SQUARE:
                status = S_IN_ARRAY;
                statusStack.addFirst(new Integer(status));
                if (!contentHandler.startArray()) return;
                break;
              default:
                status = S_IN_ERROR; // inner switch
            }
            break;

          case S_END:
            return;

          case S_IN_ERROR:
            throw new ParseException(
                getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); // switch
        }
        if (status == S_IN_ERROR) {
          throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
        }
      } while (token.type != Yytoken.TYPE_EOF);
    } catch (IOException ie) {
      status = S_IN_ERROR;
      throw ie;
    } catch (ParseException pe) {
      status = S_IN_ERROR;
      throw pe;
    } catch (RuntimeException re) {
      status = S_IN_ERROR;
      throw re;
    } catch (Error e) {
      status = S_IN_ERROR;
      throw e;
    }

    status = S_IN_ERROR;
    throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token);
  }