libjava/classpath/ChangeLog.gcj:
[official-gcc.git] / libjava / classpath / gnu / java / beans / encoder / ScanEngine.java
blobb78a8141384e194a525c42ad4dc1ce4537dedf28
1 /* ScanEngine.java
2 -- Scans the input and generates an object tree that can be written as XML.
3 Copyright (C) 2005 Free Software Foundation, Inc.
5 This file is part of GNU Classpath.
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING. If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301 USA.
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library. Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module. An independent module is a module which is not derived from
34 or based on this library. If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so. If you do not wish to do so, delete this
37 exception statement from your version. */
40 package gnu.java.beans.encoder;
42 import java.beans.Expression;
43 import java.beans.Statement;
44 import java.io.OutputStream;
45 import java.lang.reflect.Array;
46 import java.util.HashMap;
47 import java.util.IdentityHashMap;
48 import java.util.List;
49 import java.util.Stack;
51 /** <p>The <code>ScanEngine</code> is the main class of the backend of the
52 * XML persistence algorithm. It scans {@link java.beans.Expression} and
53 * {@link java.beans.Statement} instances and some raw objects via the
54 * {@link #writeObject} method and feeds it to a state machine. The
55 * state machine then constructs and object tree which is finally
56 * written as XML by a {@link Writer} implementation.</p>
58 * <p>How does it work?</p>
59 * <p>The <code>ScanEngine</code> sits below the {@link java.beans.XMLEncoder}
60 * class and is called by it exclusively. The <code>XMLEncoder</code> sends
61 * interpretive data by invoking {@link #writeExpression}, {@link #writeStatement}
62 * and {@link #writeObject}. The invocations of <code>writeExpression</code> and
63 * <code>writeStatement</code> are usually nested into each other and provide
64 * more information then necessary to generate the XML representation.
65 * Furthermore the meaning of certain <code>Expressions</code> differs
66 * depending on the enclosing elements or the inner elements have to be
67 * simply discarded.</p>
69 * <p>To cope with this state dependant nature the <code>ScanEngine</code>
70 * contains a state machine which is programmed statically (no adjustments are
71 * needed, all <code>ScanEngine</code> engines use the same setup). The
72 * <code>ScanEngine</code>'s job is to decode the <code>Expression</code>s,
73 * <code>Statement</code>s and certain objects (namely <code>String</code>,
74 * <code>null</code> objects and instances which are repeatedly provided to
75 * the encoder) into 13 low-level (event) methods, which denote the meaning of the
76 * argument. For example an <code>Expression</code> can be an array
77 * instantiation which provokes a call to {@link arrayInstantiation} or
78 * it can be a class resolution leading to a call to {@link #classResolution}.
79 * For the state machione the 13 methods are the distinct way to transit
80 * from one state to another. Whenever the <code>ScanEngine</code> calls
81 * one of the event methods the current's state successor for that event
82 * is fetched from the state machine configuration, the successpr becomes
83 * the current state and then the event method is called in the new current
84 * state. The last step allows the state instance to do something meaningful
85 * to the object tree.</p>
87 * <p>The state machine knows the concept of returning to the previous
88 * state. This is done using a stack of states which is popped every
89 * time a call to <code>writeStatement</code>, <code>writeExpression</code>
90 * in the <code>XMLEncoder</code> ends by calling the {@link #end} method.
91 * Note that due to the inheritance relationship of <code>Encoder</code>
92 * and <code>XMLEncoder</code> it is impossible for the
93 * <code>ScanEngine</code> itself to decide when an expression or statement
94 * ended. This can only be done in case of {@link #writeObject} calls because
95 * they are not nested.</p>
97 * <p>When the XML persistence mechanism reaches an object twice (and more)
98 * it should generate an XML element using the "idref" attribute and add
99 * an "id" attribute to its first instantiation. This complicates things a bit
100 * because the first instantiation will always be part of the object tree
101 * as some {@link gnu.java.beans.encoder.elements.Element} subclass instance when the
102 * second and further objects accesses are written. Therefore the {@link ObjectId}
103 * class was introduced which is shared between all the object tree elements
104 * and has the notion of an "unused" state meaning that no identification
105 * is needed. The relationship between an object and its <code>ObjectId</code>
106 * instance is stored in the <code>ScanEngine</code> and gets cleared whenever
107 * the {@link #flush} method is called. This method also writes the currently
108 * built object tree and generates the XML representation.</p>
110 * @author Robert Schuster (robertschuster@fsfe.org)
112 public class ScanEngine
115 /** Change this to true to let the ScanEngine print state transition
116 * information.
118 boolean DEBUG = false;
121 * Stores the scanner engine states as values and their names as keys.
123 HashMap states = new HashMap();
126 * Stores former scanner state and makes it possible to come back to them.
128 Stack parents = new Stack();
131 * The currently active scanner state.
133 ScannerState current;
136 * The root of an object tree that is later written to XML.
138 Root root;
141 * The Writer used to generate the XML output.
143 Writer writer;
145 /** Stores the relationship between objects and their {@link ObjectId} instance.
147 IdentityHashMap objects = new IdentityHashMap();
149 public ScanEngine(OutputStream os)
151 // TODO: Provide another Writer implementation (e.g. one that does not use
152 // the XML APIs at all).
153 writer = new StAXWriter(os);
154 root = new Root();
156 final ScannerState start = current = new GenericScannerState(root);
157 ScannerState conf;
159 // Use the ReportingScannerState to debug serialization issues.
160 register(ScannerState.DEFAULT_STATE_NAME, new IgnoringScannerState());
162 register("start", start);
164 // Special dead-end state where all transitions are ignored.
165 register("ignoreAll", new IgnoringScannerState())
166 .setDefaultSuccessor("ignoreAll");
168 // Object reference, string reference, null object
169 start.putSuccessor(ScannerState.TRANSITION_OBJECT_REFERENCE, "simple");
170 start.putSuccessor(ScannerState.TRANSITION_STRING_REFERENCE, "simple");
171 start.putSuccessor(ScannerState.TRANSITION_NULL_OBJECT, "simple");
172 register("simple", new GenericScannerState(root))
173 .setDefaultSuccessor("ignoreAll");
175 // Class resolution.
176 start.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "classRes0");
177 register("classRes0",
178 new GenericScannerState(root)).setDefaultSuccessor("ignoreAll");
180 // Object instantiation.
181 start.putSuccessor(ScannerState.TRANSITION_OBJECT_INSTANTIATION,
182 "newObj0");
183 conf = register("newObj0", new GenericScannerState(root));
184 conf.setDefaultSuccessor("ignoreAll");
186 // Simply use the start state to encode method invocations inside of
187 // objects.
188 conf.putSuccessor(ScannerState.TRANSITION_METHOD_INVOCATION, "start");
190 // Primitive instantiations.
191 start.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION,
192 "newPrimitive0");
193 register("newPrimitive0",
194 new GenericScannerState(root)).setDefaultSuccessor("ignoreAll");
196 // Object arrays use the ARRAY_GET transition to create setting the
197 // array values.
198 start.putSuccessor(ScannerState.TRANSITION_OBJECT_ARRAY_INSTANTIATION,
199 "newObjectArray");
200 conf = register("newObjectArray", new GenericScannerState(root));
201 conf.putSuccessor(ScannerState.TRANSITION_ARRAY_GET, "newOArrayGet");
202 conf.putSuccessor(ScannerState.TRANSITION_ARRAY_SET, "ignoreAll");
203 conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "ignoreAll");
204 conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION,
205 "ignoreAll");
207 // Get here when a value is set in the array.
208 register("newOArrayGet",
209 conf = new GenericScannerState(root));
211 conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION,
212 "newOArrayGet_ignoreFirstInteger");
214 // "newArrayGet_ignoreFirstInteger" is set up mostly identical like the "start"
215 // state. Otherwise things would not behave the same when done inside
216 // arrays.
217 conf.putSuccessor(ScannerState.TRANSITION_OBJECT_REFERENCE, "simple");
218 conf.putSuccessor(ScannerState.TRANSITION_STRING_REFERENCE, "simple");
219 conf.putSuccessor(ScannerState.TRANSITION_NULL_OBJECT, "simple");
220 conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "classRes0");
221 conf.putSuccessor(ScannerState.TRANSITION_OBJECT_INSTANTIATION, "newObj0");
222 conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_ARRAY_INSTANTIATION,
223 "newPrimitiveArray");
224 conf.putSuccessor(ScannerState.TRANSITION_OBJECT_ARRAY_INSTANTIATION,
225 "newObjectArray");
227 conf = register("newOArrayGet_ignoreFirstInteger",
228 new GenericScannerState(root, 1));
230 // In non-int primitive arrays class resolutions can happen
231 // but they should be ignored.
232 conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "ignoreAll");
234 // Spurious object and string references occur when setting array
235 // elements. This suppresses them.
236 conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION,
237 "ignoreAll");
238 conf.putSuccessor(ScannerState.TRANSITION_OBJECT_REFERENCE, "ignoreAll");
239 conf.putSuccessor(ScannerState.TRANSITION_STRING_REFERENCE, "ignoreAll");
241 conf.setDefaultSuccessor("start");
243 // Primitive arrays use the ARRAY_SET transition to create setting the
244 // array values. This turned out to be the only working solution.
245 // When primitive arrays were handled by ARRAY_GET the values in boolean
246 // arrays were always skipped.
247 start.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_ARRAY_INSTANTIATION,
248 "newPrimitiveArray");
249 conf = register("newPrimitiveArray", new GenericScannerState(root));
250 conf.putSuccessor(ScannerState.TRANSITION_ARRAY_GET, "ignoreAll");
251 conf.putSuccessor(ScannerState.TRANSITION_ARRAY_SET, "newPArraySet");
252 conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "ignoreAll");
253 conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION,
254 "ignoreAll");
256 conf = register("newPArraySet", new GenericScannerState(root));
257 conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION,
258 "newPArraySet_ignoreFirstInteger");
260 // Primitive arrays ignore all kinds of non-primitive object information.
261 conf.putSuccessor(ScannerState.TRANSITION_OBJECT_REFERENCE,
262 "ignoreAll");
263 conf.putSuccessor(ScannerState.TRANSITION_STRING_REFERENCE, "ignoreAll");
264 conf.putSuccessor(ScannerState.TRANSITION_NULL_OBJECT, "ignoreAll");
265 conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "ingoreAll");
266 conf.putSuccessor(ScannerState.TRANSITION_OBJECT_INSTANTIATION, "ignoreAll");
267 conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_ARRAY_INSTANTIATION,
268 "ignoreAll");
269 conf.putSuccessor(ScannerState.TRANSITION_OBJECT_ARRAY_INSTANTIATION,
270 "ignoreAll");
272 conf = register("newPArraySet_ignoreFirstInteger",
273 new GenericScannerState(root, 1));
275 // In non-int primitive arrays class resolutions can happen
276 // but they should be ignored.
277 conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "ignoreAll");
279 // Spurious object and string references occur when setting array
280 // elements. This suppresses them.
281 conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION,
282 "ignoreAll");
283 conf.putSuccessor(ScannerState.TRANSITION_OBJECT_REFERENCE, "ignoreAll");
284 conf.putSuccessor(ScannerState.TRANSITION_STRING_REFERENCE, "ignoreAll");
285 conf.setDefaultSuccessor("start");
289 /** Registers a <code>ScannerState</code> under a certain name.
291 * @param name Name of the state
292 * @param state The <code>ScannerState</code> instance.
293 * @return The second argument.
295 private ScannerState register(String name, ScannerState state)
297 state.init(name);
299 states.put(name, state);
301 return state;
304 /** Generates or returns an id for the given object which can be activated
305 * later if the object is suitable.
307 * <p>Objects are unsuitable if they are an instance of a primitive wrapper
308 * or String.</p>
310 * @param value The object to retrieve an id for.
311 * @return The id for the object or <code>null</code>.
313 private ObjectId retrieveId(Object value)
315 Class valueClass = value.getClass();
316 ObjectId id = null;
318 // Although multiple accesses to Class objects are not handled
319 // through ids we generate one for them, too. This allows us to detect
320 // second time references to such objects in the writeObject method
321 // and handle them in a special way.
322 if (valueClass != String.class
323 && valueClass.getSuperclass() != Number.class
324 && valueClass != Boolean.class)
326 if ((id = (ObjectId) objects.get(value)) == null)
328 id = new ObjectId(valueClass);
329 objects.put(value, id);
333 return id;
336 /** Scans the argument and calls one of event methods. See
337 * the introduction of this class for details.
339 * @param expr The expression to serialize.
341 public void writeExpression(Expression expr)
343 String methodName = expr.getMethodName();
344 Object[] args = expr.getArguments();
345 Object target = expr.getTarget();
346 Object value = null;
350 value = expr.getValue();
352 catch (Exception e)
354 throw (InternalError)
355 new InternalError(
356 "The Expression's value should be available at this point.")
357 .initCause(e);
360 // TODO: What if the value is null?
361 ObjectId id;
362 Class valueClass = value.getClass();
364 if (target == Array.class)
366 if (methodName.equals("newInstance"))
368 id = retrieveId(value);
370 Class ct = (Class) args[0];
372 if (ct.isPrimitive() || ct == Boolean.class || ct == Byte.class
373 || ct == Short.class || ct == Integer.class || ct == Long.class
374 || ct == Float.class || ct == Double.class)
375 primitiveArrayInstantiation(ct.getName(),
376 args[1].toString(),
377 id);
378 else
379 objectArrayInstantiation(ct.getName(),
380 args[1].toString(),
381 id);
383 return;
385 else if (methodName.equals("get"))
387 arrayGet(args[1].toString());
389 // The encoder does not call the ScanEngine
390 // when an object is serialized that we already know.
391 // We test for this situation and insert the object reference
392 // manually.
393 // Since there is already a workaround for the Class class
394 // in writeObject we have to except it from this behavior.
395 id = (ObjectId) objects.get(value);
396 if (id != null && valueClass != Class.class)
398 objectReference(id);
399 end();
402 return;
404 else if (methodName.equals("set"))
406 arraySet(args[1].toString());
407 return;
411 id = retrieveId(value);
413 if (target instanceof Class)
415 if (methodName.equals("new"))
417 Class targetClass = (Class) target;
419 // All primitive types have short-hand forms for their
420 // constructors.
421 if (valueClass == Boolean.class)
422 primitiveInstantiation("boolean", args[0].toString());
423 else if (valueClass == Byte.class)
424 primitiveInstantiation("byte", args[0].toString());
425 else if (valueClass == Short.class)
426 primitiveInstantiation("short", args[0].toString());
427 else if (valueClass == Integer.class)
428 primitiveInstantiation("int", args[0].toString());
429 else if (valueClass == Long.class)
430 primitiveInstantiation("long", args[0].toString());
431 else if (valueClass == Float.class)
432 primitiveInstantiation("float", args[0].toString());
433 else if (valueClass == Double.class)
434 primitiveInstantiation("double", args[0].toString());
435 else
436 objectInstantiation(targetClass.getName(), id);
438 return;
440 else if (value instanceof Class)
442 String className = ((Class) value).getName();
444 // At this point we know that some *static* method will be called.
446 if (methodName.equals("forName"))
448 // However "Class.forName" represents class resolution and has a
449 // special syntax.
450 classResolution(className);
451 return;
453 else if (methodName.equals("getField"))
455 // The same goes for "Class.getField".
456 // Note: The name of the wanted field is given in
457 // the argument array.
458 staticFieldAccess(className, args[0].toString());
459 return;
461 else
463 // If nothing fits it is just a static method
464 // invocation which we decode as such.
465 staticMethodInvocation(className, methodName);
466 return;
470 else if (target instanceof List)
472 // Special behavior for indexed get and set method for list-style
473 // classes.
474 // The arguments are in the args array but we need them as subelements.
475 if (methodName.equals("get"))
477 listGet();
478 return;
480 else if (methodName.equals("set"))
482 listSet();
483 return;
487 // If nothing else could be used then this is a normal
488 // method invocation.
489 methodInvocation(methodName);
493 * Ends the current state and returns to the last one.
495 public void end()
497 current.end();
499 if (DEBUG) System.err.print("back from " + current.getName());
501 ScannerState oldCurrent = current;
502 current = (ScannerState) parents.pop();
504 if (DEBUG) System.err.println(" to " + current.getName());
508 * Returns to the last state and deletes the last element in the object tree.
510 public void revoke()
512 ScannerState oldCurrent = current;
513 current = (ScannerState) parents.pop();
515 root.deleteLast();
518 /** Scans the argument and calls one of event methods. See
519 * the introduction of this class for details.
521 * @param stmt The statement to serialize.
523 public void writeStatement(Statement stmt)
525 // This is a simplified version of writeExpression. Everything
526 // that would not create something that is embedded in a <void> tag
527 // is left out (instantiation, getters, ...).
528 // TODO: Is this the right thing to do?
530 String methodName = stmt.getMethodName();
531 Object target = stmt.getTarget();
532 Object[] args = stmt.getArguments();
534 if (target == Array.class && methodName.equals("set"))
536 arraySet(args[1].toString());
537 return;
540 if (target instanceof List)
542 if (methodName.equals("set"))
544 listSet();
545 return;
549 // If nothing else could be used then this is a normal
550 // method invocation.
551 methodInvocation(methodName);
554 /** Scans the argument and calls one of event methods. See
555 * the introduction of this class for details.
557 * @param o The object to serialize.
559 public boolean writeObject(Object o)
561 ObjectId id = null;
563 if (o == null)
565 // Handle null objects which have a special syntax.
566 nullObject();
567 end();
569 else if (o.getClass() == String.class)
571 // Handle strings which are treated extremely special
572 // in the encoder (they are never converted into a
573 // Expression).
574 stringReference((String) o);
575 end();
577 else if ((id = (ObjectId) objects.get(o)) != null)
579 // Multiple references to a Class object do not generate
580 // an object reference but we use the id to detect that
581 // situation.
582 if (o.getClass() == Class.class)
584 classResolution(((Class) o).getName());
585 end();
586 return false;
589 // If our object has a corresponding ObjectId instance
590 // then generate an objectReference. This will
591 // initialize the id (= brings it in the "used" state)
592 // when this is the first referal.
593 objectReference(id);
594 end();
595 return false;
598 return true;
602 * Writes the currently constructed object tree out as
603 * XML and clears the object to {@link ObjectId} relations.
605 public void flush()
607 // Make all references unreachable. That means we have to generate
608 // new object ids.
609 objects.clear();
611 root.traverse(writer);
614 /** Writes the final bits if the object tree and closes the stream
615 * afterwards.
617 public void close()
619 flush();
620 root.close(writer);
624 * Does a transition from one state to another using the given event.
626 * <p>This involves saving the current state, retrieving it's
627 * successor and setting it as the current state.</p>
629 * @param transition One of {@link ScannerStates]'s transition constants.
631 private void transition(int transition)
633 parents.push(current);
635 String stateName = current.getSuccessor(transition);
637 if (DEBUG)
639 System.err.println("from state: " + current.getName() + "\n\troute: "
640 + ScannerState.transitionNames[transition]
641 + "\n\t\tto state: "
642 + stateName);
645 ScannerState newState = (ScannerState) states.get(stateName);
647 newState.enter(new Context(current.getName(), current.getCalls()));
649 assert (newState != null) : "State '" + stateName + "' was not defined.";
651 current = newState;
654 /** Event method that denotes a (non-static) method invocation.
656 * <p>More details about this method can be found in this
657 * class' introduction.</p>
659 * @param methodName The name of the method which is called.
661 void methodInvocation(String methodName)
663 transition(ScannerState.TRANSITION_METHOD_INVOCATION);
665 current.methodInvocation(methodName);
668 /** Event method that denotes a static method invocation.
670 * <p>More details about this method can be found in this
671 * class' introduction.</p>
673 * @param methodName The name of the method which is called.
674 * @param className The name of the class in which the method is called.
676 void staticMethodInvocation(String className, String methodName)
678 transition(ScannerState.TRANSITION_STATIC_METHOD_INVOCATION);
680 current.staticMethodInvocation(className, methodName);
683 /** Event method that denotes the retrieval of a static field's value.
685 * <p>More details about this method can be found in this
686 * class' introduction.</p>
688 * @param fieldName The name of the field whose value is retrieved.
689 * @param className The name of the class in which the method is called.
691 void staticFieldAccess(String className, String fieldName)
693 transition(ScannerState.TRANSITION_STATIC_FIELD_ACCESS);
695 current.staticFieldAccess(className, fieldName);
698 /** Event method that denotes the resolution of a class.
700 * <p>More details about this method can be found in this
701 * class' introduction.</p>
703 * @param className The name of the class in which the method is called.
705 void classResolution(String className)
707 transition(ScannerState.TRANSITION_CLASS_RESOLUTION);
709 current.classResolution(className);
712 /** Event method that denotes the instantiation of an object.
714 * <p>More details about this method can be found in this
715 * class' introduction.</p>
717 * @param className The name of the class in which the method is called.
718 * @param objectId An ObjectId instance which can be activated later.
720 void objectInstantiation(String className, ObjectId objectId)
722 transition(ScannerState.TRANSITION_OBJECT_INSTANTIATION);
724 current.objectInstantiation(className, objectId);
727 /** Event method that denotes the instantiation of a primitive.
729 * <p>More details about this method can be found in this
730 * class' introduction.</p>
732 * @param primitiveName One of "boolean, "byte", "short", "int", "long"
733 * , "float" or "double"
734 * @param valueAsString The value of the primitive as a String.
736 void primitiveInstantiation(String primitiveName, String valueAsString)
738 transition(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION);
740 current.primitiveInstantiation(primitiveName, valueAsString);
743 /** Event method that denotes the instantiation of an object array.
745 * <p>More details about this method can be found in this
746 * class' introduction.</p>
748 * @param arrayClassName The array's class name.
749 * @param objectId An ObjectId instance which can be activated later.
750 * @param lengthAsString The array's length as String.
752 void objectArrayInstantiation(String arrayClassName, String lengthAsString,
753 ObjectId objectId)
755 transition(ScannerState.TRANSITION_OBJECT_ARRAY_INSTANTIATION);
757 current.objectArrayInstantiation(arrayClassName, lengthAsString, objectId);
760 /** Event method that denotes the instantiation of a primitive array.
762 * <p>More details about this method can be found in this
763 * class' introduction.</p>
765 * @param arrayClassName The array's class name.
766 * @param objectId An ObjectId instance which can be activated later.
767 * @param lengthAsString The array's length as String.
769 void primitiveArrayInstantiation(String arrayClassName, String lengthAsString,
770 ObjectId objectId)
772 transition(ScannerState.TRANSITION_PRIMITIVE_ARRAY_INSTANTIATION);
774 current.objectArrayInstantiation(arrayClassName, lengthAsString, objectId);
777 /** Event method that denotes the setting of a value in an array.
779 * <p>More details about this method can be found in this
780 * class' introduction.</p>
782 * @param indexAsString The index to as a String.
784 void arraySet(String indexAsString)
786 transition(ScannerState.TRANSITION_ARRAY_SET);
788 current.arraySet(indexAsString);
791 /** Event method that denotes the retrieval of a value in an array.
793 * <p>More details about this method can be found in this
794 * class' introduction.</p>
796 * @param indexAsString The index to as a String.
798 void arrayGet(String indexAsString)
800 transition(ScannerState.TRANSITION_ARRAY_GET);
802 current.arrayGet(indexAsString);
805 /** Event method that denotes the setting of a value in a list.
807 * <p>More details about this method can be found in this
808 * class' introduction.</p>
810 void listSet()
812 transition(ScannerState.TRANSITION_LIST_SET);
814 current.listSet();
817 /** Event method that denotes the retrieval of a value in a list.
819 * <p>More details about this method can be found in this
820 * class' introduction.</p>
822 void listGet()
824 transition(ScannerState.TRANSITION_LIST_GET);
826 current.listGet();
829 /** Event method that denotes the null value.
831 void nullObject()
833 transition(ScannerState.TRANSITION_NULL_OBJECT);
835 current.nullObject();
838 /** Event method that denotes a string.
840 * @param string The string that should be written.
842 void stringReference(String string)
844 transition(ScannerState.TRANSITION_STRING_REFERENCE);
846 current.stringReference(string);
849 /** Event method that denotes a reference to an existing object.
851 * @param id The ObjectId to be used.
853 void objectReference(ObjectId id)
855 transition(ScannerState.TRANSITION_OBJECT_REFERENCE);
857 current.objectReference(id);