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

Quick Search    Search Deep

Source code: com/trapezium/chisel/cleaners/KeyValueRemover.java


1   /*
2    * @(#)KeyValueRemover.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.cleaners;
12  
13  import com.trapezium.vrml.VrmlElement;
14  import com.trapezium.vrml.fields.ISField;
15  import com.trapezium.vrml.fields.Field;
16  import com.trapezium.vrml.fields.MFFieldValue;
17  import com.trapezium.vrml.fields.FieldValue;
18  import com.trapezium.vrml.node.Node;
19  import com.trapezium.vrml.node.PROTO;
20  import com.trapezium.vrml.Scene;
21  import com.trapezium.chisel.*;
22  
23  import java.util.BitSet;
24  import java.util.Hashtable;
25  
26  /**
27   *  The KeyValueRemover removes keys and corresponding keyValues if the
28   *  following conditions are encountered:
29   *
30   *  1.  a key of the form:
31   *
32   *          ... a a a ....
33   *                ^ this middle value (one or more) and corresponding
34   *                  keyValue entries are removed.
35   *
36   *  2.  a keyValue of the form
37   *
38   *           ... a a a ....
39   *                 ^ this middle keyValue (one or more) and corresponding
40   *                   key entries are removed.
41   *  
42   *  @author          Johannes N. Johannsen
43   *  @version         b73, 1 July 1998
44   */
45  
46  public class KeyValueRemover extends InterpolatorMinimizer {
47      protected Hashtable valueKillTable;
48      protected BitSet valueKillBits;
49      
50      /** Class constructor, super class handles only keys */
51      public KeyValueRemover() {
52          super( "Removing unnecessary keyValues" );
53          valueKillTable = new Hashtable();
54      }
55      
56      public void attemptOptimization( Node n ) {
57          Field key = n.getField( "key" );
58          Field keyValue = n.getField( "keyValue" );
59          // If either of these fields are in a PROTO and are defined with IS
60          // do nothing
61          VrmlElement nodeParent = n.getParent();
62          if ( nodeParent instanceof Scene ) {
63              VrmlElement grandParent = nodeParent.getParent();
64              if ( grandParent instanceof PROTO ) {
65                  if ( key != null ) {
66                      int firstKeyToken = key.getFirstTokenOffset();
67                      if ( firstKeyToken != -1 ) {
68                          int nextKeyToken = dataSource.getNextToken( firstKeyToken );
69                          if ( nextKeyToken != -1 ) {
70                              if ( dataSource.sameAs( nextKeyToken, "IS" )) {
71                                  return;
72                              }
73                          }
74                      }
75                  }
76                  if ( keyValue != null ) {
77                      int firstKeyToken = keyValue.getFirstTokenOffset();
78                      if ( firstKeyToken != -1 ) {
79                          int nextKeyToken = dataSource.getNextToken( firstKeyToken );
80                          if ( nextKeyToken != -1 ) {
81                              if ( dataSource.sameAs( nextKeyToken, "IS" )) {
82                                  return;
83                              }
84                          }
85                      }
86                  }
87              }
88          }
89  
90          if ( key != null ) {
91              FieldValue keysfv = keyValue.getFieldValue();
92              MFFieldValue mfKeyValue = null;
93              if ( keysfv instanceof MFFieldValue ) {
94                  mfKeyValue = (MFFieldValue)keysfv;
95              }
96              FieldValue keyFv = key.getFieldValue();
97              MFFieldValue mfKey = null;
98              if ( keyFv instanceof MFFieldValue ) {
99                  mfKey = (MFFieldValue)keyFv;
100             }
101             if (( mfKeyValue != null ) && ( mfKeyValue.getRawValueCount() > 0 )) {
102                 int factor = getInterpolatorFactor( n );
103                 // here have to adjust factor for multiple-keyValue interpolators
104                 int checkCount = mfKeyValue.getRawValueCount()/factor;
105                 if ( checkCount > 0 ) {
106                     if ( createBitSet( mfKey, mfKeyValue, checkCount, factor )) {
107                         if ( replaceable( key )) {
108                             if ( keyFv.getFirstTokenOffset() != -1 ) {
109                                 replaceRange( keyFv.getFirstTokenOffset(), keyFv.getLastTokenOffset(), new KeyInfo( n, Key, keyKillBits, valueKillBits, checkCount ));
110                             }
111                         }
112                         if ( replaceable( keyValue )) {
113                             FieldValue fv = keyValue.getFieldValue();
114                             if ( fv.getFirstTokenOffset() != -1 ) {
115                                 replaceRange( fv.getFirstTokenOffset(), fv.getLastTokenOffset(), new KeyInfo( n, KeyValue, keyKillBits, valueKillBits, checkCount ));
116                             }
117                         }
118                     }
119                 }
120             }
121         }
122     }
123 
124     /** Create if necessary the BitSets associated with a key field in 
125      *  an interpolator.  The values "keyKillBits" and "valueKillBits"
126      *  are initialized in either case.
127      *
128      *  @param mfKey the interpolator key field
129      *  @param mfKeyValue the interpolator keyValue field
130      *  @param keyCount the number of key values
131      *  @param factor how many numeric values associated with each keyValue entry
132      *
133      *  @return true if there is something to remove, otherwise false
134      */
135     boolean createBitSet( MFFieldValue mfKey, MFFieldValue mfKeyValue, int keyCount, int factor ) {
136         if ( keyKillTable.get( mfKey ) != null ) {
137             keyKillBits = (BitSet)keyKillTable.get( mfKey );
138             valueKillBits = (BitSet)valueKillTable.get( mfKey );
139             // all value instances must agree on the removal
140             removeDups( valueKillBits, keyCount, mfKeyValue, factor, true );
141             return( true );
142         } else {
143             keyKillBits = new BitSet( keyCount );
144             valueKillBits = new BitSet( keyCount );
145             boolean result = removeDups( keyKillBits, keyCount, mfKey, 1, false );
146             result = removeDups( valueKillBits, keyCount, mfKeyValue, factor, false ) || result;
147             keyKillTable.put( mfKey, keyKillBits );
148             valueKillTable.put( mfKey, valueKillBits );
149             return( result );
150         }
151     }
152 
153     /** Mark for removal middle entries in a sequence of identical entries.
154      *
155      *  @param killBits the BitSet used to mark entries for removal
156      *  @param numberEntries number of entries to check
157      *  @param vals the entry values
158      *  @param factor number of numeric values for each entry
159      *  @param checkPreviousValues  for keyValue removal, all PROTO instance
160      *     keyValues must agree on the removal.  If this parameter is true,
161      *     previous values of the killBits are checked and possibly changed.
162      *
163      *  @return true if there is anything marked, otherwise false
164      */
165     boolean removeDups( BitSet killBits, int numberEntries, MFFieldValue vals, int factor, boolean checkPreviousValues ) {
166         int ckcount = 0;
167         float[] currentVal = new float[ factor ];
168         float[] firstVal = new float[ factor ];
169         int numberConsecutiveValues = 0;
170         dataSource.setState( vals.getFirstTokenOffset() );
171         boolean result = false;
172         for ( int i = 0; i < numberEntries; i++ ) {
173             for ( int j = 0; j < factor; j++ ) {
174                 int scanner = dataSource.skipNonNumbers();
175                 float f = dataSource.getFloat( scanner );
176                 if ( i == 0 ) {
177                     firstVal[j] = f;
178                 } else {
179                     currentVal[ j ] = f;
180                 }
181                 scanner = dataSource.getNextToken();
182             }
183             if ( i > 0 ) {
184                 boolean match = true;
185                 for ( int j = 0; j < factor; j++ ) {
186                     if ( firstVal[j] != currentVal[j] ) {
187                         match = false;
188                         break;
189                     }
190                 }
191                 if ( match ) {
192                     if ( numberConsecutiveValues == 0 ) {
193                         numberConsecutiveValues = 2;
194                     } else {
195                         numberConsecutiveValues++;
196                     }
197                 } else {
198                     numberConsecutiveValues = 0;
199                     for ( int j = 0; j < factor; j++ ) {
200                         firstVal[j] = currentVal[j];
201                     }
202                 }
203             }
204             if (( i > 0 ) && ( numberConsecutiveValues > 2 )) {
205                 if ( !checkPreviousValues ) {
206                     killBits.set( i - 1 );
207                 }
208                 result = true;
209             } else if ( checkPreviousValues ) {
210                 if ( i > 0 ) {
211                     killBits.clear( i - 1 );
212                 }
213             }
214         }
215         return( result );
216     }
217 }