/* ScanEngine.java 
 -- Scans the input and generates an object tree that can be written as XML.
 Copyright (C) 2005 Free Software Foundation, Inc.

 This file is part of GNU Classpath.

 GNU Classpath is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2, or (at your option)
 any later version.

 GNU Classpath is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with GNU Classpath; see the file COPYING.  If not, write to the
 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 02110-1301 USA.

 Linking this library statically or dynamically with other modules is
 making a combined work based on this library.  Thus, the terms and
 conditions of the GNU General Public License cover the whole
 combination.

 As a special exception, the copyright holders of this library give you
 permission to link this library with independent modules to produce an
 executable, regardless of the license terms of these independent
 modules, and to copy and distribute the resulting executable under
 terms of your choice, provided that you also meet, for each linked
 independent module, the terms and conditions of the license of that
 module.  An independent module is a module which is not derived from
 or based on this library.  If you modify this library, you may extend
 this exception to your version of the library, but you are not
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */


package gnu.java.beans.encoder;

import java.beans.Expression;
import java.beans.Statement;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Stack;

/** <p>The <code>ScanEngine</code> is the main class of the backend of the
 * XML persistence algorithm. It scans {@link java.beans.Expression} and
 * {@link java.beans.Statement} instances and some raw objects via the
 * {@link #writeObject} method and feeds it to a state machine. The
 * state machine then constructs and object tree which is finally
 * written as XML by a {@link Writer} implementation.</p>
 * 
 * <p>How does it work?</p>
 * <p>The <code>ScanEngine</code> sits below the {@link java.beans.XMLEncoder}
 * class and is called by it exclusively. The <code>XMLEncoder</code> sends
 * interpretive data by invoking {@link #writeExpression}, {@link #writeStatement}
 * and {@link #writeObject}. The invocations of <code>writeExpression</code> and
 * <code>writeStatement</code> are usually nested into each other and provide
 * more information then necessary to generate the XML representation.
 * Furthermore the meaning of certain <code>Expressions</code> differs
 * depending on the enclosing elements or the inner elements have to be
 * simply discarded.</p>
 * 
 * <p>To cope with this state dependant nature the <code>ScanEngine</code>
 * contains a state machine which is programmed statically (no adjustments are
 * needed, all <code>ScanEngine</code> engines use the same setup). The
 * <code>ScanEngine</code>'s job is to decode the <code>Expression</code>s,
 * <code>Statement</code>s and certain objects (namely <code>String</code>,
 * <code>null</code> objects and instances which are repeatedly provided to
 * the encoder) into 13 low-level (event) methods, which denote the meaning of the
 * argument. For example an <code>Expression</code> can be an array
 * instantiation which provokes a call to {@link arrayInstantiation} or
 * it can be a class resolution leading to a call to {@link #classResolution}.
 * For the state machione the 13 methods are the distinct way to transit
 * from one state to another. Whenever the <code>ScanEngine</code> calls
 * one of the event methods the current's state successor for that event
 * is fetched from the state machine configuration, the successpr becomes
 * the current state and then the event method is called in the new current
 * state. The last step allows the state instance to do something meaningful
 * to the object tree.</p>
 * 
 * <p>The state machine knows the concept of returning to the previous
 * state. This is done using a stack of states which is popped every
 * time a call to <code>writeStatement</code>, <code>writeExpression</code>
 * in the <code>XMLEncoder</code> ends by calling the {@link #end} method.
 * Note that due to the inheritance relationship of <code>Encoder</code>
 * and <code>XMLEncoder</code> it is impossible for the
 * <code>ScanEngine</code> itself to decide when an expression or statement
 * ended. This can only be done in case of {@link #writeObject} calls because
 * they are not nested.</p>
 * 
 * <p>When the XML persistence mechanism reaches an object twice (and more)
 * it should generate an XML element using the "idref" attribute and add
 * an "id" attribute to its first instantiation. This complicates things a bit
 * because the first instantiation will always be part of the object tree
 * as some {@link gnu.java.beans.encoder.elements.Element} subclass instance when the
 * second and further objects accesses are written. Therefore the {@link ObjectId}
 * class was introduced which is shared between all the object tree elements
 * and has the notion of an "unused" state meaning that no identification
 * is needed. The relationship between an object and its <code>ObjectId</code>
 * instance is stored in the <code>ScanEngine</code> and gets cleared whenever
 * the {@link #flush} method is called. This method also writes the currently
 * built object tree and generates the XML representation.</p>
 * 
 * @author Robert Schuster (robertschuster@fsfe.org)
 */
public class ScanEngine
{
  
  /** Change this to true to let the ScanEngine print state transition
   * information.
   */
  boolean DEBUG = false;

  /**
   * Stores the scanner engine states as values and their names as keys.
   */
  HashMap states = new HashMap();

  /**
   * Stores former scanner state and makes it possible to come back to them.
   */
  Stack parents = new Stack();

  /**
   * The currently active scanner state.
   */
  ScannerState current;

  /**
   * The root of an object tree that is later written to XML.
   */
  Root root;

  /**
   * The Writer used to generate the XML output.
   */
  Writer writer;

  /** Stores the relationship between objects and their {@link ObjectId} instance.
   */
  IdentityHashMap objects = new IdentityHashMap();
  
  public ScanEngine(OutputStream os)
  {
    // TODO: Provide another Writer implementation (e.g. one that does not use
    // the XML APIs at all).
    writer = new StAXWriter(os);
    root = new Root();

    final ScannerState start = current = new GenericScannerState(root);;
    ScannerState conf;

    // Use the ReportingScannerState to debug serialization issues.
    register(ScannerState.DEFAULT_STATE_NAME, new IgnoringScannerState());

    register("start", start);

    // Special dead-end state where all transitions are ignored.
    register("ignoreAll", new IgnoringScannerState())
      .setDefaultSuccessor("ignoreAll");

    // Object reference, string reference, null object
    start.putSuccessor(ScannerState.TRANSITION_OBJECT_REFERENCE, "simple");
    start.putSuccessor(ScannerState.TRANSITION_STRING_REFERENCE, "simple");
    start.putSuccessor(ScannerState.TRANSITION_NULL_OBJECT, "simple");
    register("simple", new GenericScannerState(root))
      .setDefaultSuccessor("ignoreAll");

    // Class resolution.
    start.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "classRes0");
    register("classRes0",
             new GenericScannerState(root)).setDefaultSuccessor("ignoreAll");

    // Object instantiation.
    start.putSuccessor(ScannerState.TRANSITION_OBJECT_INSTANTIATION,
                       "newObj0");
    conf = register("newObj0", new GenericScannerState(root));
    conf.setDefaultSuccessor("ignoreAll");
    
    // Simply use the start state to encode method invocations inside of
    // objects.
    conf.putSuccessor(ScannerState.TRANSITION_METHOD_INVOCATION, "start");

    // Primitive instantiations.
    start.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION,
                       "newPrimitive0");
    register("newPrimitive0",
             new GenericScannerState(root)).setDefaultSuccessor("ignoreAll");

    // Object arrays use the ARRAY_GET transition to create setting the
    // array values.
    start.putSuccessor(ScannerState.TRANSITION_OBJECT_ARRAY_INSTANTIATION,
                       "newObjectArray");
    conf = register("newObjectArray", new GenericScannerState(root));
    conf.putSuccessor(ScannerState.TRANSITION_ARRAY_GET, "newOArrayGet");
    conf.putSuccessor(ScannerState.TRANSITION_ARRAY_SET, "ignoreAll");
    conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "ignoreAll");
    conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION,
                      "ignoreAll");
    
    // Get here when a value is set in the array.
    register("newOArrayGet",
             conf = new GenericScannerState(root));
    
    conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION,
                      "newOArrayGet_ignoreFirstInteger");
    
    // "newArrayGet_ignoreFirstInteger" is set up mostly identical like the "start"
    // state. Otherwise things would not behave the same when done inside
    // arrays.
    conf.putSuccessor(ScannerState.TRANSITION_OBJECT_REFERENCE, "simple");
    conf.putSuccessor(ScannerState.TRANSITION_STRING_REFERENCE, "simple");
    conf.putSuccessor(ScannerState.TRANSITION_NULL_OBJECT, "simple");
    conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "classRes0");
    conf.putSuccessor(ScannerState.TRANSITION_OBJECT_INSTANTIATION, "newObj0");
    conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_ARRAY_INSTANTIATION,
                      "newPrimitiveArray");
    conf.putSuccessor(ScannerState.TRANSITION_OBJECT_ARRAY_INSTANTIATION,
                      "newObjectArray");
    
    conf = register("newOArrayGet_ignoreFirstInteger",
                    new GenericScannerState(root, 1));
    
    // In non-int primitive arrays class resolutions can happen
    // but they should be ignored.
    conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "ignoreAll");
    
    // Spurious object and string references occur when setting array
    // elements. This suppresses them.
    conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION,
                      "ignoreAll");
    conf.putSuccessor(ScannerState.TRANSITION_OBJECT_REFERENCE, "ignoreAll");
    conf.putSuccessor(ScannerState.TRANSITION_STRING_REFERENCE, "ignoreAll");
    
    conf.setDefaultSuccessor("start");

    // Primitive arrays use the ARRAY_SET transition to create setting the
    // array values. This turned out to be the only working solution.
    // When primitive arrays were handled by ARRAY_GET the values in boolean
    // arrays were always skipped.
    start.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_ARRAY_INSTANTIATION,
                       "newPrimitiveArray");
    conf = register("newPrimitiveArray", new GenericScannerState(root));
    conf.putSuccessor(ScannerState.TRANSITION_ARRAY_GET, "ignoreAll");
    conf.putSuccessor(ScannerState.TRANSITION_ARRAY_SET, "newPArraySet");
    conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "ignoreAll");
    conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION,
                      "ignoreAll");
    
    conf = register("newPArraySet", new GenericScannerState(root));
    conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION,
                      "newPArraySet_ignoreFirstInteger");
    
    // Primitive arrays ignore all kinds of non-primitive object information.
    conf.putSuccessor(ScannerState.TRANSITION_OBJECT_REFERENCE,
                      "ignoreAll");
    conf.putSuccessor(ScannerState.TRANSITION_STRING_REFERENCE, "ignoreAll");
    conf.putSuccessor(ScannerState.TRANSITION_NULL_OBJECT, "ignoreAll");
    conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "ingoreAll");
    conf.putSuccessor(ScannerState.TRANSITION_OBJECT_INSTANTIATION, "ignoreAll");
    conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_ARRAY_INSTANTIATION,
                      "ignoreAll");
    conf.putSuccessor(ScannerState.TRANSITION_OBJECT_ARRAY_INSTANTIATION,
                      "ignoreAll");

    conf = register("newPArraySet_ignoreFirstInteger",
                    new GenericScannerState(root, 1));
    
    // In non-int primitive arrays class resolutions can happen
    // but they should be ignored.
    conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "ignoreAll");
    
    // Spurious object and string references occur when setting array
    // elements. This suppresses them.
    conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION,
                      "ignoreAll");
    conf.putSuccessor(ScannerState.TRANSITION_OBJECT_REFERENCE, "ignoreAll");
    conf.putSuccessor(ScannerState.TRANSITION_STRING_REFERENCE, "ignoreAll");
    conf.setDefaultSuccessor("start");

  }

  /** Registers a <code>ScannerState</code> under a certain name.
   * 
   * @param name Name of the state
   * @param state The <code>ScannerState</code> instance.
   * @return The second argument.
   */
  private ScannerState register(String name, ScannerState state)
  {
    state.init(name);
    
    states.put(name, state);

    return state;
  }
  
  /** Generates or returns an id for the given object which can be activated
   * later if the object is suitable.
   * 
   * <p>Objects are unsuitable if they are an instance of a primitive wrapper
   * or String.</p>
   * 
   * @param value The object to retrieve an id for. 
   * @return The id for the object or <code>null</code>.
   */
  private ObjectId retrieveId(Object value)
  {
    Class valueClass = value.getClass();
    ObjectId id = null;
    
    // Although multiple accesses to Class objects are not handled
    // through ids we generate one for them, too. This allows us to detect
    // second time references to such objects in the writeObject method
    // and handle them in a special way.
    if (valueClass != String.class
        && valueClass.getSuperclass() != Number.class
        && valueClass != Boolean.class)
      {
        if ((id = (ObjectId) objects.get(value)) == null)
          {
            id = new ObjectId(valueClass);
            objects.put(value, id);
          }
      }
    
    return id;
  }

  /** Scans the argument and calls one of event methods. See
   * the introduction of this class for details.
   * 
   * @param expr The expression to serialize.
   */
  public void writeExpression(Expression expr)
  {
    String methodName = expr.getMethodName();
    Object[] args = expr.getArguments();
    Object target = expr.getTarget();
    Object value = null;
    
    try
      {
        value = expr.getValue();
      }
    catch (Exception e)
      {
        throw (InternalError)
          new InternalError(
          "The Expression's value should be available at this point.")
          .initCause(e);
      }

    // TODO: What if the value is null?
    ObjectId id;
    Class valueClass = value.getClass();

    if (target == Array.class)
      {
        if (methodName.equals("newInstance"))
          {
            id = retrieveId(value);
            
            Class ct = (Class) args[0];
            
            if (ct.isPrimitive() || ct == Boolean.class || ct == Byte.class
                || ct == Short.class || ct == Integer.class || ct == Long.class
                || ct == Float.class || ct == Double.class)
              primitiveArrayInstantiation(ct.getName(),
                                          args[1].toString(),
                                          id);
            else
              objectArrayInstantiation(ct.getName(),
                                       args[1].toString(),
                                       id);
            
            return;
          }
        else if (methodName.equals("get"))
          {
            arrayGet(args[1].toString());

            // The encoder does not call the ScanEngine
            // when an object is serialized that we already know.
            // We test for this situation and insert the object reference
            // manually.
            // Since there is already a workaround for the Class class
            // in writeObject we have to except it from this behavior.
            id = (ObjectId) objects.get(value);
            if (id != null && valueClass != Class.class)
              {
                objectReference(id);
                end();
              }
            
            return;
          }
        else if (methodName.equals("set"))
          {
            arraySet(args[1].toString());
            return;
          }
      }
    
    id = retrieveId(value);

    if (target instanceof Class)
      {
        if (methodName.equals("new"))
          {
            Class targetClass = (Class) target;

            // All primitive types have short-hand forms for their
            // constructors.
            if (valueClass == Boolean.class)
              primitiveInstantiation("boolean", args[0].toString());
            else if (valueClass == Byte.class)
              primitiveInstantiation("byte", args[0].toString());
            else if (valueClass == Short.class)
              primitiveInstantiation("short", args[0].toString());
            else if (valueClass == Integer.class)
              primitiveInstantiation("int", args[0].toString());
            else if (valueClass == Long.class)
              primitiveInstantiation("long", args[0].toString());
            else if (valueClass == Float.class)
              primitiveInstantiation("float", args[0].toString());
            else if (valueClass == Double.class)
              primitiveInstantiation("double", args[0].toString());
            else
              objectInstantiation(targetClass.getName(), id);

            return;
          }
        else if (value instanceof Class)
          {
            String className = ((Class) value).getName();

            // At this point we know that some *static* method will be called.

            if (methodName.equals("forName"))
              {
                // However "Class.forName" represents class resolution and has a
                // special syntax.
                classResolution(className);
                return;
              }
            else if (methodName.equals("getField"))
              {
                // The same goes for "Class.getField".
                // Note: The name of the wanted field is given in
                // the argument array.
                staticFieldAccess(className, args[0].toString());
                return;
              }
            else
              {
                // If nothing fits it is just a static method
                // invocation which we decode as such.
                staticMethodInvocation(className, methodName);
                return;
              }
          }
      }
    else if (target instanceof List)
      {
        // Special behavior for indexed get and set method for list-style
        // classes.
        // The arguments are in the args array but we need them as subelements.
        if (methodName.equals("get"))
          {
            listGet();
            return;
          }
        else if (methodName.equals("set"))
          {
            listSet();
            return;
          }
      }

    // If nothing else could be used then this is a normal
    // method invocation.
    methodInvocation(methodName);
  }

  /**
   * Ends the current state and returns to the last one.
   */
  public void end()
  {
    current.end();

    if (DEBUG) System.err.print("back from " + current.getName());

    ScannerState oldCurrent = current;
    current = (ScannerState) parents.pop();

    if (DEBUG) System.err.println(" to " + current.getName());
  }

  /**
   * Returns to the last state and deletes the last element in the object tree.
   */
  public void revoke()
  {
    ScannerState oldCurrent = current;
    current = (ScannerState) parents.pop();

    root.deleteLast();
  }

  /** Scans the argument and calls one of event methods. See
   * the introduction of this class for details.
   * 
   * @param stmt The statement to serialize.
   */
  public void writeStatement(Statement stmt)
  {
    // This is a simplified version of writeExpression. Everything
    // that would not create something that is embedded in a <void> tag
    // is left out (instantiation, getters, ...).
    // TODO: Is this the right thing to do?

    String methodName = stmt.getMethodName();
    Object target = stmt.getTarget();
    Object[] args = stmt.getArguments();

    if (target == Array.class && methodName.equals("set"))
      {
        arraySet(args[1].toString());
        return;
      }

    if (target instanceof List)
      {
        if (methodName.equals("set"))
          {
            listSet();
            return;
          }
      }

    // If nothing else could be used then this is a normal
    // method invocation.
    methodInvocation(methodName);
  }

  /** Scans the argument and calls one of event methods. See
   * the introduction of this class for details.
   * 
   * @param o The object to serialize.
   */
  public boolean writeObject(Object o)
  {
    ObjectId id = null;

    if (o == null)
      {
        // Handle null objects which have a special syntax.
        nullObject();
        end();
      }
    else if (o.getClass() == String.class)
      {
        // Handle strings which are treated extremely special
        // in the encoder (they are never converted into a
        // Expression).
        stringReference((String) o);
        end();
      }
    else if ((id = (ObjectId) objects.get(o)) != null)
      {
        // Multiple references to a Class object do not generate
        // an object reference but we use the id to detect that
        // situation.
        if (o.getClass() == Class.class)
          {
            classResolution(((Class) o).getName());
            end();
            return false;
          }
        
        // If our object has a corresponding ObjectId instance
        // then generate an objectReference. This will 
        // initialize the id (= brings it in the "used" state)
        // when this is the first referal.
        objectReference(id);
        end();
        return false;
      }

    return true;
  }

  /**
   * Writes the currently constructed object tree out as
   * XML and clears the object to {@link ObjectId} relations.
   */
  public void flush()
  {
    // Make all references unreachable. That means we have to generate
    // new object ids.
    objects.clear();

    root.traverse(writer);
  }

  /** Writes the final bits if the object tree and closes the stream
   * afterwards.
   */
  public void close()
  {
    flush();
    root.close(writer);
  }

  /**
   * Does a transition from one state to another using the given event.
   * 
   * <p>This involves saving the current state, retrieving it's
   * successor and setting it as the current state.</p>
   * 
   * @param transition One of {@link ScannerStates]'s transition constants.
   */
  private void transition(int transition)
  {
    parents.push(current);

    String stateName = current.getSuccessor(transition);
    
    if (DEBUG)
      {
        System.err.println("from state: " + current.getName() + "\n\troute: "
                           + ScannerState.transitionNames[transition]
                           + "\n\t\tto state: "
                           + stateName);
      }
    
    ScannerState newState = (ScannerState) states.get(stateName);
    
    newState.enter(new Context(current.getName(), current.getCalls()));

    assert (newState != null) : "State '" + stateName + "' was not defined.";

    current = newState;
  }

  /** Event method that denotes a (non-static) method invocation.
   *
   * <p>More details about this method can be found in this
   * class' introduction.</p>
   * 
   * @param methodName The name of the method which is called.
   */
  void methodInvocation(String methodName)
  {
    transition(ScannerState.TRANSITION_METHOD_INVOCATION);

    current.methodInvocation(methodName);
  }

  /** Event method that denotes a static method invocation.
  *
  * <p>More details about this method can be found in this
  * class' introduction.</p>
  * 
  * @param methodName The name of the method which is called.
  * @param className The name of the class in which the method is called.
  */
  void staticMethodInvocation(String className, String methodName)
  {
    transition(ScannerState.TRANSITION_STATIC_METHOD_INVOCATION);

    current.staticMethodInvocation(className, methodName);
  }

  /** Event method that denotes the retrieval of a static field's value.
  *
  * <p>More details about this method can be found in this
  * class' introduction.</p>
  * 
  * @param fieldName The name of the field whose value is retrieved.
  * @param className The name of the class in which the method is called.
  */
  void staticFieldAccess(String className, String fieldName)
  {
    transition(ScannerState.TRANSITION_STATIC_FIELD_ACCESS);

    current.staticFieldAccess(className, fieldName);
  }

  /** Event method that denotes the resolution of a class.
  *
  * <p>More details about this method can be found in this
  * class' introduction.</p>
  * 
  * @param className The name of the class in which the method is called.
  */
  void classResolution(String className)
  {
    transition(ScannerState.TRANSITION_CLASS_RESOLUTION);

    current.classResolution(className);
  }

  /** Event method that denotes the instantiation of an object.
  *
  * <p>More details about this method can be found in this
  * class' introduction.</p>
  * 
  * @param className The name of the class in which the method is called.
  * @param objectId An ObjectId instance which can be activated later.
  */
  void objectInstantiation(String className, ObjectId objectId)
  {
    transition(ScannerState.TRANSITION_OBJECT_INSTANTIATION);

    current.objectInstantiation(className, objectId);
  }

  /** Event method that denotes the instantiation of a primitive.
  *
  * <p>More details about this method can be found in this
  * class' introduction.</p>
  * 
  * @param primitiveName One of "boolean, "byte", "short", "int", "long"
  * , "float" or "double"
  * @param valueAsString The value of the primitive as a String.
  */
  void primitiveInstantiation(String primitiveName, String valueAsString)
  {
    transition(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION);

    current.primitiveInstantiation(primitiveName, valueAsString);
  }

  /** Event method that denotes the instantiation of an object array.
  *
  * <p>More details about this method can be found in this
  * class' introduction.</p>
  * 
  * @param arrayClassName The array's class name.
  * @param objectId An ObjectId instance which can be activated later.
  * @param lengthAsString The array's length as String.
  */
  void objectArrayInstantiation(String arrayClassName, String lengthAsString,
                          ObjectId objectId)
  {
    transition(ScannerState.TRANSITION_OBJECT_ARRAY_INSTANTIATION);

    current.objectArrayInstantiation(arrayClassName, lengthAsString, objectId);
  }

  /** Event method that denotes the instantiation of a primitive array.
  *
  * <p>More details about this method can be found in this
  * class' introduction.</p>
  * 
  * @param arrayClassName The array's class name.
  * @param objectId An ObjectId instance which can be activated later.
  * @param lengthAsString The array's length as String.
  */
  void primitiveArrayInstantiation(String arrayClassName, String lengthAsString,
                                ObjectId objectId)
  {
    transition(ScannerState.TRANSITION_PRIMITIVE_ARRAY_INSTANTIATION);

    current.objectArrayInstantiation(arrayClassName, lengthAsString, objectId);
  }
  
  /** Event method that denotes the setting of a value in an array.
  *
  * <p>More details about this method can be found in this
  * class' introduction.</p>
  * 
  * @param indexAsString The index to as a String.
  */
  void arraySet(String indexAsString)
  {
    transition(ScannerState.TRANSITION_ARRAY_SET);

    current.arraySet(indexAsString);
  }

  /** Event method that denotes the retrieval of a value in an array.
  *
  * <p>More details about this method can be found in this
  * class' introduction.</p>
  * 
  * @param indexAsString The index to as a String.
  */
  void arrayGet(String indexAsString)
  {
    transition(ScannerState.TRANSITION_ARRAY_GET);

    current.arrayGet(indexAsString);
  }

  /** Event method that denotes the setting of a value in a list.
  *
  * <p>More details about this method can be found in this
  * class' introduction.</p>
  */
  void listSet()
  {
    transition(ScannerState.TRANSITION_LIST_SET);

    current.listSet();
  }

  /** Event method that denotes the retrieval of a value in a list.
  *
  * <p>More details about this method can be found in this
  * class' introduction.</p>
  */
  void listGet()
  {
    transition(ScannerState.TRANSITION_LIST_GET);

    current.listGet();
  }

  /** Event method that denotes the null value.
  */
  void nullObject()
  {
    transition(ScannerState.TRANSITION_NULL_OBJECT);

    current.nullObject();
  }

  /** Event method that denotes a string.
   * 
   * @param string The string that should be written.
   */
  void stringReference(String string)
  {
    transition(ScannerState.TRANSITION_STRING_REFERENCE);

    current.stringReference(string);
  }

  /** Event method that denotes a reference to an existing object.
   * 
   * @param id The ObjectId to be used.
   */
  void objectReference(ObjectId id)
  {
    transition(ScannerState.TRANSITION_OBJECT_REFERENCE);

    current.objectReference(id);
  }

}
