OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [java/] [beans/] [encoder/] [ScanEngine.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* 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.
4
 
5
 This file is part of GNU Classpath.
6
 
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.
11
 
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.
16
 
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.
21
 
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.
26
 
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. */
38
 
39
 
40
package gnu.java.beans.encoder;
41
 
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;
50
 
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>
57
 *
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>
68
 *
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>
86
 *
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>
96
 *
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>
109
 *
110
 * @author Robert Schuster (robertschuster@fsfe.org)
111
 */
112
public class ScanEngine
113
{
114
 
115
  /** Change this to true to let the ScanEngine print state transition
116
   * information.
117
   */
118
  boolean DEBUG = false;
119
 
120
  /**
121
   * Stores the scanner engine states as values and their names as keys.
122
   */
123
  HashMap states = new HashMap();
124
 
125
  /**
126
   * Stores former scanner state and makes it possible to come back to them.
127
   */
128
  Stack parents = new Stack();
129
 
130
  /**
131
   * The currently active scanner state.
132
   */
133
  ScannerState current;
134
 
135
  /**
136
   * The root of an object tree that is later written to XML.
137
   */
138
  Root root;
139
 
140
  /**
141
   * The Writer used to generate the XML output.
142
   */
143
  Writer writer;
144
 
145
  /** Stores the relationship between objects and their {@link ObjectId} instance.
146
   */
147
  IdentityHashMap objects = new IdentityHashMap();
148
 
149
  public ScanEngine(OutputStream os)
150
  {
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();
155
 
156
    final ScannerState start = current = new GenericScannerState(root);
157
    ScannerState conf;
158
 
159
    // Use the ReportingScannerState to debug serialization issues.
160
    register(ScannerState.DEFAULT_STATE_NAME, new IgnoringScannerState());
161
 
162
    register("start", start);
163
 
164
    // Special dead-end state where all transitions are ignored.
165
    register("ignoreAll", new IgnoringScannerState())
166
      .setDefaultSuccessor("ignoreAll");
167
 
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");
174
 
175
    // Class resolution.
176
    start.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "classRes0");
177
    register("classRes0",
178
             new GenericScannerState(root)).setDefaultSuccessor("ignoreAll");
179
 
180
    // Object instantiation.
181
    start.putSuccessor(ScannerState.TRANSITION_OBJECT_INSTANTIATION,
182
                       "newObj0");
183
    conf = register("newObj0", new GenericScannerState(root));
184
    conf.setDefaultSuccessor("ignoreAll");
185
 
186
    // Simply use the start state to encode method invocations inside of
187
    // objects.
188
    conf.putSuccessor(ScannerState.TRANSITION_METHOD_INVOCATION, "start");
189
 
190
    // Primitive instantiations.
191
    start.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION,
192
                       "newPrimitive0");
193
    register("newPrimitive0",
194
             new GenericScannerState(root)).setDefaultSuccessor("ignoreAll");
195
 
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");
206
 
207
    // Get here when a value is set in the array.
208
    register("newOArrayGet",
209
             conf = new GenericScannerState(root));
210
 
211
    conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION,
212
                      "newOArrayGet_ignoreFirstInteger");
213
 
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");
226
 
227
    conf = register("newOArrayGet_ignoreFirstInteger",
228
                    new GenericScannerState(root, 1));
229
 
230
    // In non-int primitive arrays class resolutions can happen
231
    // but they should be ignored.
232
    conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "ignoreAll");
233
 
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");
240
 
241
    conf.setDefaultSuccessor("start");
242
 
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");
255
 
256
    conf = register("newPArraySet", new GenericScannerState(root));
257
    conf.putSuccessor(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION,
258
                      "newPArraySet_ignoreFirstInteger");
259
 
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");
271
 
272
    conf = register("newPArraySet_ignoreFirstInteger",
273
                    new GenericScannerState(root, 1));
274
 
275
    // In non-int primitive arrays class resolutions can happen
276
    // but they should be ignored.
277
    conf.putSuccessor(ScannerState.TRANSITION_CLASS_RESOLUTION, "ignoreAll");
278
 
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");
286
 
287
  }
288
 
289
  /** Registers a <code>ScannerState</code> under a certain name.
290
   *
291
   * @param name Name of the state
292
   * @param state The <code>ScannerState</code> instance.
293
   * @return The second argument.
294
   */
295
  private ScannerState register(String name, ScannerState state)
296
  {
297
    state.init(name);
298
 
299
    states.put(name, state);
300
 
301
    return state;
302
  }
303
 
304
  /** Generates or returns an id for the given object which can be activated
305
   * later if the object is suitable.
306
   *
307
   * <p>Objects are unsuitable if they are an instance of a primitive wrapper
308
   * or String.</p>
309
   *
310
   * @param value The object to retrieve an id for.
311
   * @return The id for the object or <code>null</code>.
312
   */
313
  private ObjectId retrieveId(Object value)
314
  {
315
    Class valueClass = value.getClass();
316
    ObjectId id = null;
317
 
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)
325
      {
326
        if ((id = (ObjectId) objects.get(value)) == null)
327
          {
328
            id = new ObjectId(valueClass);
329
            objects.put(value, id);
330
          }
331
      }
332
 
333
    return id;
334
  }
335
 
336
  /** Scans the argument and calls one of event methods. See
337
   * the introduction of this class for details.
338
   *
339
   * @param expr The expression to serialize.
340
   */
341
  public void writeExpression(Expression expr)
342
  {
343
    String methodName = expr.getMethodName();
344
    Object[] args = expr.getArguments();
345
    Object target = expr.getTarget();
346
    Object value = null;
347
 
348
    try
349
      {
350
        value = expr.getValue();
351
      }
352
    catch (Exception e)
353
      {
354
        throw (InternalError)
355
          new InternalError(
356
          "The Expression's value should be available at this point.")
357
          .initCause(e);
358
      }
359
 
360
    // TODO: What if the value is null?
361
    ObjectId id;
362
    Class valueClass = value.getClass();
363
 
364
    if (target == Array.class)
365
      {
366
        if (methodName.equals("newInstance"))
367
          {
368
            id = retrieveId(value);
369
 
370
            Class ct = (Class) args[0];
371
 
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);
382
 
383
            return;
384
          }
385
        else if (methodName.equals("get"))
386
          {
387
            arrayGet(args[1].toString());
388
 
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)
397
              {
398
                objectReference(id);
399
                end();
400
              }
401
 
402
            return;
403
          }
404
        else if (methodName.equals("set"))
405
          {
406
            arraySet(args[1].toString());
407
            return;
408
          }
409
      }
410
 
411
    id = retrieveId(value);
412
 
413
    if (target instanceof Class)
414
      {
415
        if (methodName.equals("new"))
416
          {
417
            Class targetClass = (Class) target;
418
 
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);
437
 
438
            return;
439
          }
440
        else if (value instanceof Class)
441
          {
442
            String className = ((Class) value).getName();
443
 
444
            // At this point we know that some *static* method will be called.
445
 
446
            if (methodName.equals("forName"))
447
              {
448
                // However "Class.forName" represents class resolution and has a
449
                // special syntax.
450
                classResolution(className);
451
                return;
452
              }
453
            else if (methodName.equals("getField"))
454
              {
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;
460
              }
461
            else
462
              {
463
                // If nothing fits it is just a static method
464
                // invocation which we decode as such.
465
                staticMethodInvocation(className, methodName);
466
                return;
467
              }
468
          }
469
      }
470
    else if (target instanceof List)
471
      {
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"))
476
          {
477
            listGet();
478
            return;
479
          }
480
        else if (methodName.equals("set"))
481
          {
482
            listSet();
483
            return;
484
          }
485
      }
486
 
487
    // If nothing else could be used then this is a normal
488
    // method invocation.
489
    methodInvocation(methodName);
490
  }
491
 
492
  /**
493
   * Ends the current state and returns to the last one.
494
   */
495
  public void end()
496
  {
497
    current.end();
498
 
499
    if (DEBUG) System.err.print("back from " + current.getName());
500
 
501
    ScannerState oldCurrent = current;
502
    current = (ScannerState) parents.pop();
503
 
504
    if (DEBUG) System.err.println(" to " + current.getName());
505
  }
506
 
507
  /**
508
   * Returns to the last state and deletes the last element in the object tree.
509
   */
510
  public void revoke()
511
  {
512
    ScannerState oldCurrent = current;
513
    current = (ScannerState) parents.pop();
514
 
515
    root.deleteLast();
516
  }
517
 
518
  /** Scans the argument and calls one of event methods. See
519
   * the introduction of this class for details.
520
   *
521
   * @param stmt The statement to serialize.
522
   */
523
  public void writeStatement(Statement stmt)
524
  {
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?
529
 
530
    String methodName = stmt.getMethodName();
531
    Object target = stmt.getTarget();
532
    Object[] args = stmt.getArguments();
533
 
534
    if (target == Array.class && methodName.equals("set"))
535
      {
536
        arraySet(args[1].toString());
537
        return;
538
      }
539
 
540
    if (target instanceof List)
541
      {
542
        if (methodName.equals("set"))
543
          {
544
            listSet();
545
            return;
546
          }
547
      }
548
 
549
    // If nothing else could be used then this is a normal
550
    // method invocation.
551
    methodInvocation(methodName);
552
  }
553
 
554
  /** Scans the argument and calls one of event methods. See
555
   * the introduction of this class for details.
556
   *
557
   * @param o The object to serialize.
558
   */
559
  public boolean writeObject(Object o)
560
  {
561
    ObjectId id = null;
562
 
563
    if (o == null)
564
      {
565
        // Handle null objects which have a special syntax.
566
        nullObject();
567
        end();
568
      }
569
    else if (o.getClass() == String.class)
570
      {
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();
576
      }
577
    else if ((id = (ObjectId) objects.get(o)) != null)
578
      {
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)
583
          {
584
            classResolution(((Class) o).getName());
585
            end();
586
            return false;
587
          }
588
 
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;
596
      }
597
 
598
    return true;
599
  }
600
 
601
  /**
602
   * Writes the currently constructed object tree out as
603
   * XML and clears the object to {@link ObjectId} relations.
604
   */
605
  public void flush()
606
  {
607
    // Make all references unreachable. That means we have to generate
608
    // new object ids.
609
    objects.clear();
610
 
611
    root.traverse(writer);
612
  }
613
 
614
  /** Writes the final bits if the object tree and closes the stream
615
   * afterwards.
616
   */
617
  public void close()
618
  {
619
    flush();
620
    root.close(writer);
621
  }
622
 
623
  /**
624
   * Does a transition from one state to another using the given event.
625
   *
626
   * <p>This involves saving the current state, retrieving it's
627
   * successor and setting it as the current state.</p>
628
   *
629
   * @param transition One of {@link ScannerStates]'s transition constants.
630
   */
631
  private void transition(int transition)
632
  {
633
    parents.push(current);
634
 
635
    String stateName = current.getSuccessor(transition);
636
 
637
    if (DEBUG)
638
      {
639
        System.err.println("from state: " + current.getName() + "\n\troute: "
640
                           + ScannerState.transitionNames[transition]
641
                           + "\n\t\tto state: "
642
                           + stateName);
643
      }
644
 
645
    ScannerState newState = (ScannerState) states.get(stateName);
646
 
647
    newState.enter(new Context(current.getName(), current.getCalls()));
648
 
649
    assert (newState != null) : "State '" + stateName + "' was not defined.";
650
 
651
    current = newState;
652
  }
653
 
654
  /** Event method that denotes a (non-static) method invocation.
655
   *
656
   * <p>More details about this method can be found in this
657
   * class' introduction.</p>
658
   *
659
   * @param methodName The name of the method which is called.
660
   */
661
  void methodInvocation(String methodName)
662
  {
663
    transition(ScannerState.TRANSITION_METHOD_INVOCATION);
664
 
665
    current.methodInvocation(methodName);
666
  }
667
 
668
  /** Event method that denotes a static method invocation.
669
  *
670
  * <p>More details about this method can be found in this
671
  * class' introduction.</p>
672
  *
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.
675
  */
676
  void staticMethodInvocation(String className, String methodName)
677
  {
678
    transition(ScannerState.TRANSITION_STATIC_METHOD_INVOCATION);
679
 
680
    current.staticMethodInvocation(className, methodName);
681
  }
682
 
683
  /** Event method that denotes the retrieval of a static field's value.
684
  *
685
  * <p>More details about this method can be found in this
686
  * class' introduction.</p>
687
  *
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.
690
  */
691
  void staticFieldAccess(String className, String fieldName)
692
  {
693
    transition(ScannerState.TRANSITION_STATIC_FIELD_ACCESS);
694
 
695
    current.staticFieldAccess(className, fieldName);
696
  }
697
 
698
  /** Event method that denotes the resolution of a class.
699
  *
700
  * <p>More details about this method can be found in this
701
  * class' introduction.</p>
702
  *
703
  * @param className The name of the class in which the method is called.
704
  */
705
  void classResolution(String className)
706
  {
707
    transition(ScannerState.TRANSITION_CLASS_RESOLUTION);
708
 
709
    current.classResolution(className);
710
  }
711
 
712
  /** Event method that denotes the instantiation of an object.
713
  *
714
  * <p>More details about this method can be found in this
715
  * class' introduction.</p>
716
  *
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.
719
  */
720
  void objectInstantiation(String className, ObjectId objectId)
721
  {
722
    transition(ScannerState.TRANSITION_OBJECT_INSTANTIATION);
723
 
724
    current.objectInstantiation(className, objectId);
725
  }
726
 
727
  /** Event method that denotes the instantiation of a primitive.
728
  *
729
  * <p>More details about this method can be found in this
730
  * class' introduction.</p>
731
  *
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.
735
  */
736
  void primitiveInstantiation(String primitiveName, String valueAsString)
737
  {
738
    transition(ScannerState.TRANSITION_PRIMITIVE_INSTANTIATION);
739
 
740
    current.primitiveInstantiation(primitiveName, valueAsString);
741
  }
742
 
743
  /** Event method that denotes the instantiation of an object array.
744
  *
745
  * <p>More details about this method can be found in this
746
  * class' introduction.</p>
747
  *
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.
751
  */
752
  void objectArrayInstantiation(String arrayClassName, String lengthAsString,
753
                          ObjectId objectId)
754
  {
755
    transition(ScannerState.TRANSITION_OBJECT_ARRAY_INSTANTIATION);
756
 
757
    current.objectArrayInstantiation(arrayClassName, lengthAsString, objectId);
758
  }
759
 
760
  /** Event method that denotes the instantiation of a primitive array.
761
  *
762
  * <p>More details about this method can be found in this
763
  * class' introduction.</p>
764
  *
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.
768
  */
769
  void primitiveArrayInstantiation(String arrayClassName, String lengthAsString,
770
                                ObjectId objectId)
771
  {
772
    transition(ScannerState.TRANSITION_PRIMITIVE_ARRAY_INSTANTIATION);
773
 
774
    current.objectArrayInstantiation(arrayClassName, lengthAsString, objectId);
775
  }
776
 
777
  /** Event method that denotes the setting of a value in an array.
778
  *
779
  * <p>More details about this method can be found in this
780
  * class' introduction.</p>
781
  *
782
  * @param indexAsString The index to as a String.
783
  */
784
  void arraySet(String indexAsString)
785
  {
786
    transition(ScannerState.TRANSITION_ARRAY_SET);
787
 
788
    current.arraySet(indexAsString);
789
  }
790
 
791
  /** Event method that denotes the retrieval of a value in an array.
792
  *
793
  * <p>More details about this method can be found in this
794
  * class' introduction.</p>
795
  *
796
  * @param indexAsString The index to as a String.
797
  */
798
  void arrayGet(String indexAsString)
799
  {
800
    transition(ScannerState.TRANSITION_ARRAY_GET);
801
 
802
    current.arrayGet(indexAsString);
803
  }
804
 
805
  /** Event method that denotes the setting of a value in a list.
806
  *
807
  * <p>More details about this method can be found in this
808
  * class' introduction.</p>
809
  */
810
  void listSet()
811
  {
812
    transition(ScannerState.TRANSITION_LIST_SET);
813
 
814
    current.listSet();
815
  }
816
 
817
  /** Event method that denotes the retrieval of a value in a list.
818
  *
819
  * <p>More details about this method can be found in this
820
  * class' introduction.</p>
821
  */
822
  void listGet()
823
  {
824
    transition(ScannerState.TRANSITION_LIST_GET);
825
 
826
    current.listGet();
827
  }
828
 
829
  /** Event method that denotes the null value.
830
  */
831
  void nullObject()
832
  {
833
    transition(ScannerState.TRANSITION_NULL_OBJECT);
834
 
835
    current.nullObject();
836
  }
837
 
838
  /** Event method that denotes a string.
839
   *
840
   * @param string The string that should be written.
841
   */
842
  void stringReference(String string)
843
  {
844
    transition(ScannerState.TRANSITION_STRING_REFERENCE);
845
 
846
    current.stringReference(string);
847
  }
848
 
849
  /** Event method that denotes a reference to an existing object.
850
   *
851
   * @param id The ObjectId to be used.
852
   */
853
  void objectReference(ObjectId id)
854
  {
855
    transition(ScannerState.TRANSITION_OBJECT_REFERENCE);
856
 
857
    current.objectReference(id);
858
  }
859
 
860
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.