Package nexj.core.rpc.json

Source Code of nexj.core.rpc.json.JSONParser

package nexj.core.rpc.json;

import java.util.ArrayList;
import java.util.Collection;

import nexj.core.scripting.GenericParser;
import nexj.core.scripting.GlobalEnvironment;
import nexj.core.scripting.ParserException;
import nexj.core.util.HashTab;
import nexj.core.util.Lookup;
import nexj.core.util.TextPosition;

/**
* Parses a JSON message into a map.
*/
public class JSONParser extends GenericParser
{
   // constants

   /**
    * Open Container {
    */
   protected final static int TOKEN_OBRACE = 1;

   /**
    * Closing Container }
    */
   protected final static int TOKEN_CBRACE = 2;

   /**
    * Open [
    */
   protected final static int TOKEN_OBRACKET = 3;

   /**
    * Closing ]
    */
   protected final static int TOKEN_CBRACKET = 4;

   /**
    * Comma ,
    */
   protected final static int TOKEN_COMMA = 5;

   /**
    * Colon :
    */
   protected final static int TOKEN_COLON = 6;

   /**
    * Atom (null, boolean, number, string).
    */
   protected final static int TOKEN_ATOM = 7;

   // constructors

   /**
    * Create a JSON parser with a given global environment for interning symbols.
    *
    * @param globalEnv The global environment, into which to store the symbols.
    */
   public JSONParser(GlobalEnvironment env)
   {
      super(env);
   }

   // operations

   /**
    * Parses buffer for a JSON Array.
    *
    * @return The parsed out array as collection.
    * @throws ParserException if a syntax error has been encountered.
    */
   protected Collection parseArray()
   {
      ArrayList list = new ArrayList(4);
      Object value = null;
      boolean bHasValue = false;

      ++m_nListDepth;

      if (getCurToken() != TOKEN_CBRACKET)
      {
         for (;;)
         {
            value = parseElement();
            list.add(value);
            bHasValue = true;

            if (getCurToken() == TOKEN_CBRACKET)
            {
               forgetToken();
               --m_nListDepth;

               break;
            }
            else if (getCurToken() == TOKEN_COMMA)
            {
               if (!bHasValue)
               {
                  fail("err.parser.json.array.unexpectedComma", null, getCurTokenPos());
               }
               else
               {
                  forgetToken();
                  bHasValue = false;
                  value = null;
               }
            }
            else
            {
               fail("err.parser.json.array.unexpectedToken", new Object[] { m_tokenValue }, getCurTokenPos());
            }
         }
      }
      else
      {
         forgetToken();
      }

      return list;
   }

   /**
    * Parses buffer for a JSON value - array, object or primitive.
    *
    * @return The internal representation of the value.
    * @throws ParserException if a syntax error has been encountered.
    */
   protected Object parseValue()
   {
      Object value = null;

      for (;;)
      {
         switch (getCurToken())
         {
            case TOKEN_EOF:
               fail("err.parser.listEOF", null, getCurTokenPos());

            case TOKEN_OBRACE:
               value = parseElement();

               return value;

            case TOKEN_ATOM:
               value = m_tokenValue;
               forgetToken();

               return value;

            case TOKEN_OBRACKET:
               forgetToken();
               value = parseArray();

               return value;

            default:
               fail("err.parser.json.value.unexpectedToken", new Object[] { m_tokenValue }, getCurTokenPos());
         }
      }
   }

   /**
    * Parses buffer for a JSON object.
    *
    * @return The internal representation of the object.
    * @throws ParserException if a syntax error has been encountered.
    */
   protected Object parseObject()
   {
      String sKey = null;
      Object value = null;
      Lookup objMap = new HashTab(4);

      ++m_nListDepth;

      if (getCurToken() != TOKEN_CBRACE)
      {
         for (;;)
         {
            value = parseValue();
            // key
            if (value instanceof String)
            {
               sKey = (String)m_tokenValue;
            }
            else
            {
               fail("err.parser.json.object.unexpectedKeyValue", new Object[] { value }, getCurTokenPos());
            }

            // value
            if (getCurToken() != TOKEN_COLON)
            {
               fail("err.parser.unexpectedToken", new Object[] { m_tokenValue }, getCurTokenPos());
            }
            else
            {
               forgetToken();
               value = parseValue();
               objMap.put(sKey, value);

               if (getCurToken() == TOKEN_CBRACE)
               {
                  forgetToken();
                  --m_nListDepth;

                  break;
               }
               else if (getCurToken() == TOKEN_COMMA)
               {
                  forgetToken();
                  sKey = null;
                  value = null;
               }
               else
               {
                  fail("err.parser.unexpectedToken", new Object[] { m_tokenValue },getCurTokenPos());
               }
            }
         }
      }
      else
      {
         forgetToken();
      }

      return objMap;
   }

   /**
    * Parses buffer for a single JSON element - object, array or primitive.
    *
    * @return The internal representation of the element.
    * @throws ParserException if a syntax error has been encountered.
    */
   protected Object parseElement()
   {
      TextPosition pos = null;
      Object obj;

      switch (getCurToken())
      {
         // must start with an open brace, open array, or primitive
         case TOKEN_ATOM:
            obj = m_tokenValue;
            forgetToken();

            return obj;

         case TOKEN_OBRACKET:
            if (m_posMap != null)
            {
               pos = getCurTokenPos();
            }

            forgetToken();
            obj = parseArray();

            if (m_posMap != null && obj != null)
            {
               m_posMap.put(obj, pos);
            }

            return obj;

         case TOKEN_OBRACE:
            if (m_posMap != null)
            {
               pos = getCurTokenPos();
            }

            forgetToken();
            obj = parseObject();

            if (m_posMap != null && obj != null)
            {
               m_posMap.put(obj, pos);
            }

            return obj;

         case TOKEN_CBRACE:
         case TOKEN_CBRACKET:
         case TOKEN_COMMA:
         case TOKEN_COLON:
            fail("err.parser.json.value.unexpectedToken", new Object[] { m_tokenValue },getCurTokenPos());

            return null;

         default:

            return EOF;
      }
   }

   /**
    * @see nexj.core.scripting.GenericParser#parseToken()
    */
   protected int parseToken()
   {
      for (;;)
      {
         while (Character.isWhitespace((char)getCurChar()))
         {
            forgetChar();
         }

         if (m_textPosReader != null)
         {
            m_nTokenLine = m_textPosReader.getTextPosition().getLine();
            m_nTokenColumn = m_textPosReader.getTextPosition().getColumn();
         }

         m_tokenValue = Character.toString((char)m_ch);

         switch (m_ch)
         {
            case CHAR_EOF:

               return TOKEN_EOF;

            case '"':
               m_tokenValue = parseString();

               return TOKEN_ATOM;

            case ':':
               forgetChar();

               return TOKEN_COLON;

            case '{':
               forgetChar();

               return TOKEN_OBRACE;

            case '}':
               forgetChar();

               return TOKEN_CBRACE;

            case '[':
               forgetChar();

               return TOKEN_OBRACKET;

            case ']':
               forgetChar();

               return TOKEN_CBRACKET;

            case ',':
               forgetChar();

               return TOKEN_COMMA;

            case '-':
               switch (getNextChar())
               {
                  case '0':
                  case '1':
                  case '2':
                  case '3':
                  case '4':
                  case '5':
                  case '6':
                  case '7':
                  case '8':
                  case '9':
                     m_tokenValue = parseNumber(0, -1, 0, false);

                     return TOKEN_ATOM;
               }

               fail("err.parser.unexpectedToken", new Object[] { Character.toString((char)m_ch) }, getCurTextPosition());
               forgetChar();
               m_tokenValue = "";

               return TOKEN_NONE;

            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
               m_tokenValue = parseNumber(0, 1, 0, false);

               return TOKEN_ATOM;

            case '.':
               switch (getNextChar())
               {
                  case '0':
                  case '1':
                  case '2':
                  case '3':
                  case '4':
                  case '5':
                  case '6':
                  case '7':
                  case '8':
                  case '9':
                     m_tokenValue = parseNumber(10, 1, 2, true);

                     return TOKEN_ATOM;
               }

               fail("err.parser.unexpectedToken", new Object[] { Character.toString((char)m_ch) }, getCurTextPosition());
               forgetChar();
               m_tokenValue = "";

               return TOKEN_NONE;

            case 'n':
               m_tokenValue = parseNULL();

               return TOKEN_ATOM;

            case 't':
            case 'f':
               m_tokenValue = parseBoolean();

               return TOKEN_ATOM;

            default:
               fail("err.parser.unexpectedToken", new Object[] { m_tokenValue }, getCurTextPosition());
               forgetChar();
               m_tokenValue = "";

               return TOKEN_NONE;
         }
      }
   }

   /**
    * Parses buffer for a JSON null.
    *
    * @return The internal representation of null.
    * @throws ParserException if a syntax error has been encountered.
    */
   protected Object parseNULL()
   {
      m_tokenBuf.setLength(0);
      m_tokenBuf.append((char)getCurChar());

      for (;;)
      {
         markReader1();
         getNextChar();

         if (Character.isLetter((char)m_ch))
         {
            m_tokenBuf.append((char)m_ch);

            continue;
         }

         resetReader();

         break;
      }

      String sValue = m_tokenBuf.toString();

      if (!sValue.equals("null"))
      {
         fail("err.parser.unexpectedToken", new Object[] { sValue }, getCurTextPosition());
      }

      return null;
   }

   /**
    * Parses buffer for a JSON boolean.
    *
    * @return The internal representation of the boolean value.
    * @throws ParserException if a syntax error has been encountered.
    */
   protected Boolean parseBoolean()
   {
      m_tokenBuf.setLength(0);
      m_tokenBuf.append((char)getCurChar());
      Boolean value = null;

      for (;;)
      {
         markReader1();
         getNextChar();

         if (Character.isLetter((char)m_ch))
         {
            m_tokenBuf.append((char)m_ch);

            continue;
         }

         resetReader();

         break;
      }

      String sValue = m_tokenBuf.toString();

      if (sValue.equals("true"))
      {
         value = Boolean.TRUE;
      }
      else if (sValue.equals("false"))
      {
         value = Boolean.FALSE;
      }
      else
      {
         fail("err.parser.unexpectedToken", new Object[] { sValue }, getCurTextPosition());
      }

      return value;
   }
}
TOP

Related Classes of nexj.core.rpc.json.JSONParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.