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

Quick Search    Search Deep

Source code: com/trapezium/chisel/condensers/PROTOMaker.java


1   /*
2    * @(#)PROTOMaker.java
3    *
4    * Copyright (c) 1998 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.chisel.condensers;
12  
13  import com.trapezium.pattern.Visitor;
14  import com.trapezium.vrml.grammar.VRML97;
15  import com.trapezium.vrml.VrmlElement;
16  import com.trapezium.vrml.Value;
17  import com.trapezium.vrml.node.Node;
18  import com.trapezium.vrml.node.DEFUSENode;
19  import com.trapezium.vrml.node.PROTOInstance;
20  import com.trapezium.vrml.fields.Field;
21  import com.trapezium.vrml.fields.FieldValue;
22  import com.trapezium.vrml.fields.MFFieldValue;
23  import com.trapezium.vrml.fields.SFNodeValue;
24  import com.trapezium.vrml.Scene;
25  import com.trapezium.vrml.ROUTE;
26  import com.trapezium.util.NameGenerator;
27  import com.trapezium.util.ReturnInteger;
28  import com.trapezium.chisel.*;
29  
30  import java.util.Vector;
31  import java.util.Hashtable;
32  import java.util.Enumeration;
33  
34  /**
35   *  Creates PROTOs for interpolators if they have the same keys
36   */
37  public class PROTOMaker extends Optimizer {
38  
39      class ROUTEReplacer {
40          boolean srcIsInterpolator;
41          boolean destIsInterpolator;
42          ROUTE route;
43          
44          ROUTEReplacer( ROUTE route, boolean srcIsInterpolator, boolean destIsInterpolator ) {
45              this.route = route;
46              this.srcIsInterpolator = srcIsInterpolator;
47              this.destIsInterpolator = destIsInterpolator;
48          }
49          
50          ROUTE getRoute() {
51              return( route );
52          }
53          
54          boolean isSrcInterpolator() {
55              return( srcIsInterpolator );
56          }
57          
58          boolean isDestInterpolator() {
59              return( destIsInterpolator );
60          }
61      }
62      
63      boolean attemptedFirstNode;
64      Hashtable interpolatorLists;
65      Scene theScene;
66      NameGenerator nameGenerator;
67      boolean printedPROTOs;
68      
69    public PROTOMaker() {
70      super( "Interpolator", "Creating PROTOs for interpolators..." );
71      reset();
72    }
73    
74    public void reset() {
75      interpolatorLists = new Hashtable();
76      theScene = null;
77      nameGenerator = new NameGenerator();
78      attemptedFirstNode = false;
79      printedPROTOs = false;
80    }
81    
82    public boolean isROUTElistener() {
83        return( true );
84    }
85  
86      /** Add an interpolator node to the corresponding list */
87      void addInterpolator( String interpolatorType, Node n ) {
88          InterpolatorEntry ie = (InterpolatorEntry)interpolatorLists.get( interpolatorType );
89          if ( ie == null ) {
90              ie = new InterpolatorEntry( interpolatorType, nameGenerator );
91              interpolatorLists.put( interpolatorType, ie );
92          }
93          ie.add( n );
94      }
95      
96      /** Is a specific node in the replacement interpolator lists? */
97      boolean isInterpolatorReplaced( String interpolatorType, Node n ) {
98          InterpolatorEntry ie = (InterpolatorEntry)interpolatorLists.get( interpolatorType );
99          if ( ie == null ) {
100             return( false );
101         } else {
102             return( ie.find( n ));
103         }
104     }
105 
106     /** Check if a node name is an interpolator */
107     boolean isInterpolator( String nodeName ) {
108        if ( nodeName.compareTo( "ColorInterpolator" ) == 0 ) {
109            return( true );
110        } else if ( nodeName.compareTo( "CoordinateInterpolator" ) == 0 ) {
111            return( true );
112        } else if ( nodeName.compareTo( "NormalInterpolator" ) == 0 ) {
113            return( true );
114        } else if ( nodeName.compareTo( "OrientationInterpolator" ) == 0 ) {
115            return( true );
116        } else if ( nodeName.compareTo( "PositionInterpolator" ) == 0 ) {
117            return( true );
118        } else if ( nodeName.compareTo( "ScalarInterpolator" ) == 0 ) {
119            return( true );
120        } else {
121            return( false );
122        }
123     }
124     
125    public void attemptOptimization( Node n ) {
126        // don't mess with interpolators that are inside PROTOs
127        Scene s = (Scene)n.getScene();
128        if ( s.getPROTOparent() != null ) {
129            return;
130        }
131        // don't mess with interpolators that may have been copied due
132        // to being inside a PROTO
133        if ( n.getParent() instanceof PROTOInstance ) {
134            return;
135        }
136        if ( !attemptedFirstNode ) {
137            attemptedFirstNode = true;
138            replaceRange( 1, 1, null );
139        }
140        boolean foundInterpolator = false;
141        if ( theScene == null ) {
142            theScene = (Scene)n.getScene();
143        }
144        String nodeName = n.getBaseName();
145        if ( !VRML97.isValidFieldId( nodeName, "key" )) {
146            return;
147        }
148        if ( n.getField( "key" ) == null ) {
149            return;
150        }
151        if ( isInterpolator( nodeName )) {
152            foundInterpolator = true;
153            addInterpolator( nodeName, n );
154        } 
155        if ( foundInterpolator ) {
156            replaceRange( n.getFirstTokenOffset(), n.getLastTokenOffset(), n );
157        }
158    }
159    
160    public void attemptOptimization( ROUTE route ) {
161        String sourceObject = route.getSourceDEFname();
162        String destObject = route.getDestDEFname();
163        Scene s = (Scene)route.getScene();
164        if (( sourceObject != null ) && ( destObject != null ) && ( s != null )) {
165            DEFUSENode src  = s.getDEF( sourceObject );
166            DEFUSENode dest = s.getDEF( destObject );
167            Node srcNode = src.getNode();
168            Node destNode = dest.getNode();
169            if (( srcNode != null ) && ( destNode != null )) {
170                String srcName = srcNode.getBaseName();
171                String destName = destNode.getBaseName();
172                boolean srcIsInterpolator = isInterpolator( srcName );
173                boolean destIsInterpolator = isInterpolator( destName );
174                 if ( srcIsInterpolator && !isInterpolatorReplaced( srcName, srcNode )) {
175                     return;
176                 }
177                 if ( destIsInterpolator && !isInterpolatorReplaced( destName, destNode )) {
178                     return;
179                 }
180                if ( srcIsInterpolator || destIsInterpolator ) {
181                    replaceRange( route.getFirstTokenOffset(), route.getLastTokenOffset(), new ROUTEReplacer( route, srcIsInterpolator, destIsInterpolator ));
182                }
183            }
184       }
185    }
186 
187     void printPROTOs( TokenPrinter tp ) {
188         Enumeration keys = interpolatorLists.keys();
189         while ( keys.hasMoreElements() ) {
190             InterpolatorEntry ie = (InterpolatorEntry)interpolatorLists.get( keys.nextElement() );
191             ie.printPROTO( tp );
192         }
193     }
194     
195   public void optimize( TokenPrinter tp, Object param, int startTokenOffset, int endTokenOffset ) {
196       if (( param == null ) && !printedPROTOs ) {
197           printPROTOs( tp );
198           printedPROTOs = true;
199           tp.print( dataSource, startTokenOffset );
200       } else if ( param instanceof Node ) {
201           // in case interpolator was first node
202           if ( !printedPROTOs ) {
203               printPROTOs( tp );
204               printedPROTOs = true;
205           }
206           String nodeName = ((Node)param).getBaseName();
207           InterpolatorEntry ie = (InterpolatorEntry)interpolatorLists.get( nodeName );
208           if ( ie != null ) {
209               ie.print( tp, (Node)param );
210           }
211       } else if ( param instanceof ROUTEReplacer ) {
212           ROUTEReplacer rr = (ROUTEReplacer)param;
213           ROUTE route = rr.getRoute();
214           boolean replaceSource = rr.isSrcInterpolator();
215           boolean replaceDest = rr.isDestInterpolator();
216           tp.flush();
217           tp.print( "ROUTE" );
218              String src = route.getSourceDEFname();
219              String srcField = route.getSourceFieldName();
220              String s = src + "." + remap( srcField, replaceSource );
221              tp.print( s );
222              tp.print( "TO" );
223              String dest = route.getDestDEFname();
224              String destField = route.getDestFieldName();
225              s = dest + "." + remap( destField, replaceDest );
226              tp.print( s );
227              tp.flush();
228          }
229   }
230   
231   String remap( String interpolatorField, boolean replaceit ) {
232       if ( replaceit ) {
233           if ( interpolatorField.compareTo( "set_fraction" ) == 0 ) {
234               return( "i" );
235           } else if ( interpolatorField.compareTo( "value_changed" ) == 0 ) {
236               return( "o" );
237           } else if ( interpolatorField.compareTo( "key" ) == 0 ) {
238               return( "k" );
239           } else if ( interpolatorField.compareTo( "keyValue" ) == 0 ) {
240               return( "v" );
241           } else {
242               return( "??" );
243           }
244       } else {
245           return( interpolatorField );
246       }
247   }
248   
249   class KeyFieldEntry {
250       Field keyField;
251       ReturnInteger count;
252       
253       KeyFieldEntry( Field keyField ) {
254           this.keyField = keyField;
255           count = new ReturnInteger( 1 );
256       }
257       
258       public Field getKeyField() {
259           return( keyField );
260       }
261       
262       public int getCount() {
263           return( count.getValue() );
264       }
265       
266       public void incCount() {
267           count.incValue();
268       }
269   }
270   
271   class InterpolatorEntry {
272       // name of VRML interpolator
273       String interpolatorType;
274       
275       // generated PROTO name
276       String PROTOname;
277       
278       // vector of KeyFieldEntry, which just contain "key" field and 
279       // a count of how many identical "key" fields found
280       Vector keyFields;
281       
282       // mapping from a Node to an offset in the "keyFields" vector
283       Hashtable nodeToKeyEntry;
284       
285       NameGenerator nameGenerator;
286       
287       // offset of the most popular "key" field, which gets used
288       // as the default
289       int mostPopularKeyOffset;
290       
291       InterpolatorEntry( String interpolatorType, NameGenerator nameGenerator ) {
292           this.interpolatorType = interpolatorType;
293           this.nameGenerator = nameGenerator;
294           keyFields = new Vector();
295           nodeToKeyEntry = new Hashtable();
296           PROTOname = null;
297       }
298       
299       /** Keep count of most popular key fields, put in mapping node to key entry */
300         void add( Node n ) {
301             Field key = n.getField( "key" );
302             int keyStart = key.getFirstTokenOffset();
303             int keyEnd = key.getLastTokenOffset();
304             int keyFieldsSize = keyFields.size();
305             for ( int i = 0; i < keyFieldsSize; i++ ) {
306                 KeyFieldEntry kfe = (KeyFieldEntry)keyFields.elementAt( i );
307                 Field testField = kfe.getKeyField();
308                 if ( fieldsIdentical( keyStart, keyEnd, testField.getFirstTokenOffset(), testField.getLastTokenOffset() )) {
309                     kfe.incCount();
310                     nodeToKeyEntry.put( n, new Integer( i ));
311                     return;
312                 }
313             }
314             KeyFieldEntry kfe = new KeyFieldEntry( key );
315             keyFields.addElement( kfe );
316             nodeToKeyEntry.put( n, new Integer( keyFieldsSize ));
317         }
318         
319         /** Check if a node is registered in the list */
320         boolean find( Node n ) {
321             return( nodeToKeyEntry.get( n ) != null );
322         }
323         
324         void calculateMostPopularKeyOffset() {
325             int keyFieldsSize = keyFields.size();
326             int winner = 0;
327             int winnerCount = -1;
328             for ( int i = 0; i < keyFieldsSize; i++ ) {
329                 KeyFieldEntry kfe = (KeyFieldEntry)keyFields.elementAt( i );
330                 if ( kfe.getCount() > winnerCount ) {
331                     winner = i;
332                     winnerCount = kfe.getCount();
333                 }
334             }
335             mostPopularKeyOffset = winner;
336         }
337         
338         boolean fieldsIdentical( int f1start, int f1end, int f2start, int f2end ) {
339             int f1size = f1end - f1start + 1;
340             int f2size = f2end - f2start + 1;
341             if ( f1size != f2size ) {
342                 return( false );
343             }
344             for ( int i = f1start; i <= f1end; i++, f2start++ ) {
345                 if ( !dataSource.sameAs( i, f2start )) {
346                     return( false );
347                 }
348             }
349             return( true );
350         }
351                     
352         void printKeyField( TokenPrinter tp ) {
353             calculateMostPopularKeyOffset();
354             KeyFieldEntry kfe = (KeyFieldEntry)keyFields.elementAt( mostPopularKeyOffset );
355             tp.print( "exposedField MFFloat k" );
356             printField( tp, kfe.getKeyField(), true );
357         }
358         
359         void printField( TokenPrinter tp, Field f ) {
360             printField( tp, f, false );
361         }
362         
363         void printField( TokenPrinter tp, Field f, String nm ) {
364             tp.print( nm );
365             printField( tp, f, true );
366         }
367         
368         void printField( TokenPrinter tp, Field f, boolean skipFirst ) {
369             if ( f != null ) {
370                 int fStart = f.getFirstTokenOffset();
371                 if ( skipFirst ) {
372                     fStart++;
373                 }
374                 int fEnd = f.getLastTokenOffset();
375                 for ( int i = fStart; i <= fEnd; i++ ) {
376                     tp.print( dataSource, i );
377                 }
378             }
379         }
380         
381         /** Get the key entry offset for a node */
382         int getKeyEntryOffset( Node n ) {
383             Integer offset = (Integer)nodeToKeyEntry.get( n );
384             return( offset.intValue() );
385         }
386         
387         /** Print a node, but as a PROTO */
388       void print( TokenPrinter tp, Node n ) {
389           tp.print( PROTOname );
390           tp.print( "{" );
391           int keyEntryOffset = getKeyEntryOffset( n );
392           KeyFieldEntry kfe = (KeyFieldEntry)keyFields.elementAt( keyEntryOffset );
393           if ( keyEntryOffset != mostPopularKeyOffset ) {
394               printField( tp, n.getField( "key" ), "k" );
395           }
396           printField( tp, n.getField( "keyValue" ), "v" );
397           tp.print( "}" );
398       }
399       
400       void createPROTOname() {
401           while ( true ) {
402               String testName = nameGenerator.generateName();
403               if ( theScene.getPROTO( testName ) == null ) {
404                   PROTOname = testName;
405                   return;
406               }
407           }
408       }
409       
410       void printEventIn( TokenPrinter tp ) {
411           tp.flush();
412           tp.print( "eventIn SFFloat i" );
413           tp.flush();
414       }
415 
416         void printEventOut( TokenPrinter tp ) {
417             tp.flush();
418             tp.print( "eventOut" );
419             tp.print( VRML97.getFieldTypeString( interpolatorType, "value_changed" ));
420             tp.print( "o" );
421             tp.flush();
422         }
423       
424       void printPROTO( TokenPrinter tp ) {
425           createPROTOname();
426           tp.flush();
427           tp.print( "PROTO" );
428           tp.print( PROTOname );
429           tp.print( "[" );
430           printEventIn( tp );
431           printKeyField( tp );
432           tp.print( "exposedField" );
433           tp.print( VRML97.getFieldTypeString( interpolatorType, "keyValue" ));
434           tp.print( "v" );
435           tp.print( "[]" );
436           printEventOut( tp );
437           tp.print( "] {" );
438           tp.flush();
439           tp.print( interpolatorType );
440           tp.print( "{" );
441           tp.flush();
442           tp.print( "set_fraction IS i" );
443           tp.flush();
444           tp.print( "key IS k" );
445           tp.flush();
446           tp.print( "keyValue IS v" );
447           tp.flush();
448           tp.print( "value_changed IS o" );
449           tp.print( "} }" );
450       }
451   }
452 }