Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/trapezium/bean/BehaviorBean.java


1   /*
2    * @(#)BehaviorBean.java
3    *
4    * Copyright (c) 1999 by Trapezium Development LLC.  All Rights Reserved.
5    *
6    * The information in this file is the property of Trapezium Development LLC
7    * and may be used only in accordance with the terms of the license granted
8    * by Trapezium.
9    *
10   */
11  package com.trapezium.bean;
12  
13  import com.trapezium.parse.TokenEnumerator;
14  import com.trapezium.humanoid.Humanoid_1_0;
15  import com.trapezium.vrml.ROUTE;
16  import com.trapezium.vrml.VrmlElement;
17  import com.trapezium.vrml.Scene;
18  import com.trapezium.vrml.node.Node;
19  import com.trapezium.chisel.TokenPrinter;
20  import com.trapezium.vrml.node.DEFUSENode;
21  import com.trapezium.vrml.node.PROTOInstance;
22  import com.trapezium.vrml.node.PROTObase;
23  
24  import java.io.*;
25  import java.util.Hashtable;
26  import java.util.Enumeration;
27  import java.util.Vector;
28  
29  /** The BehaviorBean contains the set of DEFs and associated ROUTEs for a particular
30   *  behavior.  At the moment, it uses an "ultimate" root, which is the first ROUTE
31   *  in a chain of ROUTEs.  This might not be appropriate, since this might be some
32   *  sort of sensor with associated geometry.
33   *
34   *  An alternate approach, which might be better in other cases is to just use the
35   *  first TimeSensor encountered as the "ultimate" root.
36   *
37   */
38  public class BehaviorBean implements java.io.Serializable, Humanoid_1_0 {
39  
40      // the DEFs used by this behavior
41      Vector defs;
42      
43      // the ROUTEs used by this behavior
44      Vector routes;
45      
46      // no longer used, but needed if we include touch sensor stuff
47      Vector sensorContainingNodes;
48      Hashtable defToJoint;
49      Hashtable jointToDef;
50      ROUTE ultimate;
51      
52      // modification points are where token offsets have shifted
53      int[] modificationPoints;
54      int[] modificationValue;
55      int mpidx;
56      void addModificationPoint( int offset, int value ) {
57          modificationPoints[mpidx] = offset;
58          modificationValue[mpidx] = value;
59          mpidx++;
60      }
61      int getModifiedStartValue( int offset ) {
62          for ( int i = 0; i < mpidx; i++ ) {
63              if ( offset > modificationPoints[i] ) {
64                  offset += modificationValue[i];
65              }
66          }
67          return( offset );
68      }
69      int getModifiedEndValue( int offset ) {
70          for ( int i = 0; i < mpidx; i++ ) {
71              if ( offset > (modificationPoints[i] + modificationValue[i])) {
72                  offset += modificationValue[i];
73              }
74          }
75          return( offset );
76      }
77      
78      public BehaviorBean( ROUTE ultimate, Hashtable defToJoint, Hashtable jointToDef ) {
79          modificationPoints = new int[100];
80          modificationValue = new int[100];
81          mpidx = 0;
82          this.ultimate = ultimate;
83          routes = new Vector();
84          defs = new Vector();
85          sensorContainingNodes = new Vector();
86          this.defToJoint = defToJoint;
87          this.jointToDef = jointToDef;
88      }
89      
90      private void writeObject( ObjectOutputStream stream ) throws java.io.IOException  {
91          System.out.println( "BehaviorBean.writeObject" );
92          stream.defaultWriteObject();
93      }
94      
95      /** Save ROUTE info. */
96      public void saveROUTE( ROUTE route ) {
97          if ( routes.indexOf( route ) == -1 ) {
98              routes.addElement( route );
99          }
100     }
101 
102     /** Save DEF info, but only for DEFs that aren't joints. */
103     public void saveDEF( String defName ) {
104         if ( defs.indexOf( defName ) == -1 ) {
105             if ( defToJoint.get( defName ) == null ) {
106                 defs.addElement( defName );
107             }
108         }
109     }
110 
111     /** Generate VRML for this, using DEF names from the humanoid
112      *  if the ROUTE is referring to a Joint.
113      *
114      *  @param humanBean used to resolve Joint DEF names to one used by 
115      *     HumanBean in the case where the behavior was originally applied
116      *     to a different humanoid
117      *  @param ps where to print the data
118      *  @param behaviorNumber used to rename behaviors
119      *  @param defsGenerated list of DEFs that text has been generated for,
120      *     to prevent repeatedly generating text for a DEF that was used
121      *     in more than one behavior.
122      */
123     public void generateVRML( HumanBean humanBean, PrintStream ps, int behaviorNumber, Hashtable defsGenerated, Vector generatedRoutes, Hashtable generatedPROTOs ) {
124         String behaviorName = "hb_behavior_" + behaviorNumber;
125         Scene baseScene = (Scene)ultimate.getRoot();
126         replaceDEF( ultimate.getSourceDEFname(), behaviorName, baseScene );
127         ps.println( "#" );
128         ps.println( "# Generating ROUTEs for ultimate " + ultimate.getSourceDEFname() + " TO " + ultimate.getDestDEFname() );
129         ps.println( "#" );
130         generateDEFs( ps, defsGenerated, generatedPROTOs, baseScene );
131         int numberRoutes = routes.size();
132         Hashtable beanJointToDef = humanBean.getJointToDef();
133         for ( int i = 0; i < numberRoutes; i++ ) {
134             ROUTE r = (ROUTE)routes.elementAt( i );
135             if ( generatedRoutes.indexOf( r ) == -1 ) {
136                 generatedRoutes.addElement( r );
137                 generateRoute( ps, beanJointToDef, r );
138             }
139         }
140     }
141     
142     void replaceDEF( String originalName, String newName, Scene scene ) {
143         if ( originalName.compareTo( newName ) == 0 ) {
144             return;
145         }
146         TokenEnumerator te = scene.getTokenEnumerator();
147         DEFUSENode dun = scene.getDEF( originalName );
148         if ( dun != null ) {
149             int offset = getModifiedStartValue( dun.getFirstTokenOffset() + 1 );
150             te.replace( offset, newName );
151             Node n = dun.getNode();
152 
153             // possibly def is PROTO for TimeSensor
154             if ( n instanceof PROTOInstance ) {
155                 PROTOInstance pi = (PROTOInstance)n;
156                 PROTObase pb = pi.getPROTObase();
157                 n = pb.getPROTONodeType();
158                 if ( n == null ) {
159                     return;
160                 }
161             }
162             // make TimeSensor fields uniform
163             int oldSize = n.getLastTokenOffset() - n.getFirstTokenOffset();
164             System.out.println( "old range " + n.getFirstTokenOffset() + " to " + n.getLastTokenOffset() );
165 //            System.out.println( "3678 is '" + te.toString( 3678 ) + "'" );
166 //            System.out.println( "3681 is '" + te.toString( 3681 ) + "'" );
167             int originalLast = n.getLastTokenOffset();
168             if ( n.getBaseName().compareTo( "TimeSensor" ) == 0 ) {
169                 try {
170                     n.setField( "startTime 0" );
171                     n.setField( "stopTime 0" );
172                     n.setField( "enabled FALSE" );
173                 } catch ( Exception e ) {
174                     e.printStackTrace();
175                     System.out.println( "error setting TimeSensor fields" );
176                 }
177             }
178             int newSize = n.getLastTokenOffset() - n.getFirstTokenOffset();
179             if (( newSize - oldSize ) != 0 ) {
180                 addModificationPoint( originalLast, newSize - oldSize );
181             }
182             System.out.println( "new range " + n.getFirstTokenOffset() + " to " + n.getLastTokenOffset() );
183             System.out.println( "added modification point " + originalLast + ", size " + (newSize-oldSize));
184 //            System.out.println( "3678 is '" + te.toString( 3678 ) + "'" );
185 //            System.out.println( "3681 is '" + te.toString( 3681 ) + "'" );
186         }
187         int numberRoutes = routes.size();
188         for ( int i = 0; i < numberRoutes; i++ ) {
189             ROUTE r = (ROUTE)routes.elementAt( i );
190             if ( r.getSourceDEFname().compareTo( originalName ) == 0 ) {
191                 int offset = getModifiedStartValue( r.getFirstTokenOffset() + 1 );
192                 te.replace( offset, newName + "." + r.getSourceFieldName() );
193                 r.setSourceDEFname( newName );
194             }
195         }
196     }
197 
198     /** Generate text for all the DEFs used by this behavior.  The DEFs listed
199      *  in this behavior are only the ones that are used by the behavior, but
200      *  are not Joint DEFs.
201      */
202     void generateDEFs( PrintStream ps, Hashtable defsGenerated, Hashtable generatedPROTOs, Scene scene ) {
203         int numberDEFs = defs.size();
204         TokenEnumerator te = scene.getTokenEnumerator();
205         for ( int i = 1; i < numberDEFs; i++ ) {
206             String defName = (String)defs.elementAt( i );
207             generateDEF( ps, defName, scene, te, defsGenerated, generatedPROTOs );
208         }
209         String ultimateDEF = (String)defs.elementAt( 0 );
210         generateDEF( ps, ultimateDEF, scene, te, defsGenerated, generatedPROTOs );
211     }
212     
213     /** Generate text for a single DEF.  If that DEF is totally contained in another DEF,
214      *  then generate text for that other DEF (unless it was done already).
215      *
216      *  @param ps PrintStream destination of generated text
217      *  @param defName the name of the DEF to generate
218      *  @param scene the Scene containing the DEF
219      *  @param te source of text
220      *  @param defsGenerated table of DEFs already generated to prevent duplicate DEFS
221      *     (NOTE: still one DEF containing another will result in duplicates)
222      */
223     void generateDEF( PrintStream ps, String defName, Scene scene, TokenEnumerator te, Hashtable defsGenerated, Hashtable generatedPROTOs ) {
224         if ( defsGenerated.get( defName ) != null ) {
225             return;
226         }
227         defsGenerated.put( defName, defName );
228         VrmlElement defNode = scene.getDEF( defName );
229         if ( defNode == null ) {
230             return;
231         }
232         if ( defNode instanceof DEFUSENode ) {
233             DEFUSENode dun = (DEFUSENode)defNode;
234             Node n = dun.getNode();
235             if ( n instanceof PROTOInstance ) {
236                 PROTOInstance pi = (PROTOInstance)n;
237                 PROTObase pb = pi.getPROTObase();
238                 String pbName = pb.getId();
239                 if ( pbName != null ) {
240                     if ( pbName.compareTo( "Joint" ) != 0 ) {
241                         if ( generatedPROTOs.get( pb ) == null ) {
242                             generatedPROTOs.put( pb, pb );
243                             TokenPrinter tp = new TokenPrinter( te, new TokenEnumerator() );
244                             tp.printRange( getModifiedStartValue( pb.getFirstTokenOffset() ), 
245                                 getModifiedStartValue( pb.getLastTokenOffset() ), true );
246                             tp.flush();
247                             tp.saveDataSink( ps );
248                             ps.println( "#" );
249                             ps.println( "# end of PROTO from " + pb.getFirstTokenOffset() + " to " + pb.getLastTokenOffset() );
250                         }
251                     }
252                 }
253             }
254         }
255         DEFUSENode containingDEF = getContainingDEF( scene, defNode.getFirstTokenOffset() );
256         if ( containingDEF != null ) {
257             while ( true ) {
258                 defNode = containingDEF;
259                 String name = containingDEF.getId();
260                 System.out.println( "DEF contained in '" + name + "'" );
261                 if ( defsGenerated.get( name ) != null ) {
262                     return;
263                 }
264                 defsGenerated.put( name, name );
265                 DEFUSENode ctest = getContainingDEF( scene, containingDEF.getFirstTokenOffset() );
266                 if ( ctest == null ) {
267                     break;
268                 } else {
269                     containingDEF = ctest;
270                 }
271             }
272         }
273         Node test = getSensorContainingNode( defNode.getFirstTokenOffset() );
274         if ( test != null ) {
275             defNode = test;
276         }
277         TokenPrinter tp = new TokenPrinter( te, new TokenEnumerator() );
278         System.out.println( "def node goes from " + defNode.getFirstTokenOffset() + " to " + defNode.getLastTokenOffset() );
279         System.out.println( "tokens are: " + te.toString( defNode.getFirstTokenOffset() ) + ", then " + te.toString( defNode.getFirstTokenOffset() + 1 ));
280 
281         tp.printRange( getModifiedStartValue( defNode.getFirstTokenOffset()), 
282             getModifiedEndValue( defNode.getLastTokenOffset() ), true );
283         tp.flush();
284         tp.saveDataSink( ps );
285         ps.println( "#" );
286         ps.println( "# end of DEF " + defNode.getFirstTokenOffset() + " to " + defNode.getLastTokenOffset() );
287         ps.println( "# modified:  " + getModifiedStartValue( defNode.getFirstTokenOffset()) + " to " + getModifiedEndValue( defNode.getLastTokenOffset()) );
288     }
289         
290     /** Get the non-DEFfed node that contains this one, this is used
291      *  for the case where we have to also generate a sensor node parent,
292      *  since the sensor only makes sense in the context of its parent.
293      */
294     Node getSensorContainingNode( int offset ) {
295 //        System.out.println( "Searching for sensor containing DEFs" );
296         int numberSensorContainingNodes = sensorContainingNodes.size();
297         for ( int i = 0; i < numberSensorContainingNodes; i++ ) {
298             Node n = (Node)sensorContainingNodes.elementAt( i );
299             if (( n.getFirstTokenOffset() < offset ) && ( n.getLastTokenOffset() > offset )) {
300 //                System.out.println( "FOUND ONE" );
301                 return( n );
302             }
303         }
304 //        System.out.println( "Didn't FIND ONE" );
305         return( null );
306     }
307     
308     /** Add a sensor containing node */
309     public void addSensorContainingNode( Node n ) {
310         sensorContainingNodes.addElement( n );
311     }
312     
313     /** Get the DEF that contains another DEF
314      *
315      *  @param scene the authority on all DEFs
316      *  @param defOffset the tokenOffset of the DEF to check, it is contained in
317      *     another DEF if that other DEF's token offsets surround it
318      *  
319      *  @return the first containing DEF found, or null if none
320      */
321     DEFUSENode getContainingDEF( Scene scene, int defOffset ) {
322         int numberDEFs = defs.size();
323 //        System.out.println( "getContainingDEF for offset " + defOffset );
324         for ( int i = 0; i < numberDEFs; i++ ) {
325             String defName = (String)defs.elementAt( i );
326             DEFUSENode test = scene.getDEF( defName );
327             if ( test != null ) {
328                 if (( test.getFirstTokenOffset() < defOffset ) && ( test.getLastTokenOffset() > defOffset )) {
329                     return( test );
330                 }
331             }
332         }
333         return( null );
334     }
335         
336 
337     /** Generate text for a ROUTE
338      *
339      *  @param ps PrintStream destination for generated text
340      *  @param beanJointToDef table that maps Joint names to DEF names for a particular HumanBean
341      *  @param r the ROUTE to convert to text
342      */
343     void generateRoute( PrintStream ps, Hashtable beanJointToDef, ROUTE r ) {
344         String source = r.getSourceDEFname();
345         String dest = r.getDestDEFname();
346         String jointSource = (String)defToJoint.get( source );
347         String jointDest = (String)defToJoint.get( dest );
348         if ( jointSource != null ) {
349             source = (String)beanJointToDef.get( jointSource );
350         }
351         if ( jointDest != null ) {
352             dest = (String)beanJointToDef.get( jointDest );
353         }
354         ps.println( "ROUTE " + source + "." + r.getSourceFieldName() + " TO " + dest + "." + r.getDestFieldName() );
355     }
356 }