KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jacorb > idl > NameTable


1 /*
2  * JacORB - a free Java ORB
3  *
4  * Copyright (C) 1997-2004 Gerald Brose.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the Free
18  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */

20
21 package org.jacorb.idl;
22
23 /**
24  * A table of defined names
25  *
26  * @author Gerald Brose
27  * @version $Id: NameTable.java,v 1.23 2005/03/28 19:58:29 brose Exp $
28  *
29  */

30
31 import java.io.PrintWriter JavaDoc;
32 import java.util.*;
33
34 class NameTable
35 {
36
37     private static Hashtable h = new Hashtable( 10000 );
38
39     private static Hashtable shadows = new Hashtable();
40
41     private static Hashtable ancestors = new Hashtable();
42
43     /**
44      key: operation name,
45      value: interface this operation was originally defined in
46      necessary to track legal diamond inheritance of operations
47      */

48
49     private static Hashtable operationSources = new Hashtable();
50
51     private static String JavaDoc s = "";
52
53     public static Hashtable parsed_interfaces = new Hashtable();
54
55     static org.apache.log.Logger logger;
56
57     public static void init()
58     {
59         h.clear();
60         operationSources.clear();
61         shadows.clear();
62         ancestors.clear();
63
64         operationSources.clear();
65         parsed_interfaces.clear();
66
67         h.put( "char", "type" );
68         h.put( "boolean", "type" );
69         h.put( "long", "type" );
70         h.put( "long", "type" );
71         h.put( "short", "type" );
72         h.put( "int", "type" );
73         h.put( "float", "type" );
74         h.put( "double", "type" );
75         h.put( "byte", "type" );
76         h.put( "void", "type" );
77         h.put( "org.omg.CORBA.Any", "type" );
78         h.put( "org.omg.CORBA.Object", "interface" );
79
80         logger = parser.getLogger();
81     }
82
83     /**
84      * check IDL scoping rules
85      * @throws NameAlreadyDefined, or the derived IllegalRedefinition
86      */

87
88     private static void checkScopingRules( String JavaDoc name, String JavaDoc kind )
89         throws NameAlreadyDefined
90     {
91         if( logger.isDebugEnabled() )
92         {
93             logger.debug("NameTable.checkScopingRules: " +
94                          name + " kind: " + kind );
95         }
96
97         if( kind.equals( "argument" ) )
98         {
99             return; // no checks in outer scopes ???
100
}
101
102         StringTokenizer strtok =
103             new StringTokenizer( name.toUpperCase(), "." );
104
105         String JavaDoc scopes[] = new String JavaDoc[ strtok.countTokens() ];
106
107         for( int i = 0; strtok.hasMoreTokens(); i++ )
108         {
109             scopes[ i ] = strtok.nextToken();
110         }
111
112         if( logger.isDebugEnabled() )
113             logger.debug(
114                          "NameTable.checkScopingRules2: " +
115                          name + " kind: " + kind );
116
117         if( scopes.length > 1 &&
118             scopes[ scopes.length - 2 ].equals( scopes[ scopes.length - 1 ] ) )
119         {
120             throw new IllegalRedefinition( name );
121         }
122     }
123
124
125     /**
126      * define a name. If it has already been defined in this scope,
127      * an exception is thrown
128      *
129      * @param String name The name to be defined
130      * @param String kind the type of name, e.g. "type"
131      * @throws NameAlreadyDefined if the name is already defined
132      */

133
134     public static void define( String JavaDoc name, String JavaDoc kind )
135         throws NameAlreadyDefined
136     {
137         if( logger.isInfoEnabled() )
138             logger.info( "NameTable.define2: putting " +
139                         name + " kind " + kind + " hash: " +
140                         name.hashCode() );
141
142         /* check also for the all uppercase version of this name,
143            (which is also reserved to block identifiers that
144            only differ in case) */

145
146         if( h.containsKey( name ) ||
147             h.containsKey( name.toUpperCase() ) )
148         {
149             // if this name has been inherited, it is "shadowed"
150
// in this case, it is redefined if it is not an operation
151
// or interface name. If it has been
152
// explicitly defined in this scope, we have an error
153

154             if( kind.equals( "module" ) )
155             {
156                 // modules may be "reopened", no further checks or table entries
157
return;
158             }
159             else if( !shadows.containsKey( name ) ||
160                      kind.equals( "operation" ) ||
161                      kind.equals( "interface" ) )
162             {
163                 throw new NameAlreadyDefined( name );
164             }
165             else
166             {
167                 // redefine
168
if( logger.isInfoEnabled() )
169                     logger.info( "NameTable.define2: redefining " + name );
170
171                 shadows.remove( name );
172                 h.remove( name );
173
174                 // remove the inherited type definition, a new one will be
175
// added soon under this name! Addition of this line fixes
176
// bug #345
177
TypeMap.removeDefinition( name );
178             }
179         }
180
181         if( org.jacorb.idl.parser.strict_names )
182             checkScopingRules( name, kind );
183
184         h.put( name, kind );
185
186         /* block identifiers that only differ in case */
187         if( org.jacorb.idl.parser.strict_names )
188             h.put( name.toUpperCase(), "dummy" );
189
190         if( kind.equals( "operation" ) )
191             operationSources.put( name, name.substring( 0, name.lastIndexOf( "." ) ) );
192     }
193
194     private static void defineInheritedOperation( String JavaDoc name,
195                                                   String JavaDoc inheritedFrom )
196             throws NameAlreadyDefined
197     {
198
199         if( h.containsKey( name ) )
200         {
201             String JavaDoc source = null;
202             String JavaDoc opName =
203                     ( name.indexOf( "." ) < 0 ? name : name.substring( name.lastIndexOf( "." ) + 1 ) );
204             String JavaDoc presentOpName = name;
205
206             while( ( source = (String JavaDoc)operationSources.get( presentOpName ) ) != null )
207             {
208                 if( presentOpName.equals( source + "." + opName ) )
209                 {
210                     break;
211                 }
212                 presentOpName = source + "." + opName;
213
214             }
215             if( logger.isInfoEnabled() )
216             {
217                 logger.info("NameTable source of " + name
218                             + " is " + presentOpName );
219             }
220
221             String JavaDoc otherOpName = inheritedFrom + "." + opName;
222
223             while( ( source = (String JavaDoc)operationSources.get( otherOpName ) ) != null )
224             {
225                 if( otherOpName.equals( source + "." + opName ) )
226                 {
227                     break;
228                 }
229                 otherOpName = source + "." + opName;
230             }
231             if( logger.isInfoEnabled() )
232             {
233                 logger.info("NameTable other source of " + name
234                             + " is " + otherOpName );
235             }
236
237             if( otherOpName.equals( presentOpName ) )
238             {
239                 // found an operation that is inherited from
240
// the same ultimate base via different paths
241
// do nothing, as it is already defined for this
242
// interface
243
return;
244             }
245             else
246             {
247                 // illegal multiple inheritance of a the same op name
248
throw new NameAlreadyDefined( name );
249             }
250         }
251         else
252         {
253             h.put( name, "operation" );
254             operationSources.put( name, inheritedFrom );
255         }
256     }
257
258     /**
259      * define a shadowed name, i.e. an inherited name
260      * @throws NameAlreadyDefined if a name is already defined
261      */

262
263     private static void defineShadows( Hashtable shadowEntries )
264         throws NameAlreadyDefined
265     {
266         String JavaDoc firstViolation = null;
267         for( Enumeration e = shadowEntries.keys(); e.hasMoreElements(); )
268         {
269             String JavaDoc name = (String JavaDoc)e.nextElement();
270             String JavaDoc kind = (String JavaDoc)shadowEntries.get( name );
271             if( h.containsKey( name ) )
272             {
273                 firstViolation = name;
274             }
275             else
276             {
277                 h.put( name, kind );
278                 if( logger.isDebugEnabled() )
279                     logger.debug( "Put shadow " + name );
280                 shadows.put( name, "" );
281                 if( kind.equals( "operation" ) )
282                     operationSources.put( name, name.substring( 0, name.lastIndexOf( "." ) ) );
283             }
284         }
285         if( firstViolation != null )
286         {
287             throw new NameAlreadyDefined( firstViolation );
288         }
289     }
290
291     /**
292      * copy names declared in an ancestor interface to the local scope
293      * @throws NameAlreadyDefined
294      */

295
296     public static synchronized void inheritFrom( String JavaDoc name,
297                                                  SymbolList ancestors )
298         throws NameAlreadyDefined
299     {
300         Hashtable shadowNames = new Hashtable();
301         for( Enumeration e = h.keys(); e.hasMoreElements(); )
302         {
303             String JavaDoc key = (String JavaDoc)e.nextElement();
304             String JavaDoc s = null;
305             if( key.indexOf( '.' ) > 0 )
306                 s = key.substring( 0, key.lastIndexOf( '.' ) );
307             else
308                 continue;
309
310             for( Enumeration i = ancestors.v.elements(); i.hasMoreElements(); )
311             {
312                 String JavaDoc anc = ( (ScopedName)( i.nextElement() ) ).resolvedName();
313                 if( s.equals( anc ) )
314                 {
315                     String JavaDoc kind = (String JavaDoc)h.get( key );
316                     if( logger.isDebugEnabled() )
317                     {
318                         logger.debug( "NameTable.inheritFrom ancestor " + anc +
319                                        " : key " + key + " kind " + kind );
320                     }
321
322                     String JavaDoc shadowKey = name + key.substring( key.lastIndexOf( '.' ) );
323                     shadowNames.put( shadowKey, kind );
324
325                     // if the name we inherit is a typedef'd name, we need
326
// to typedef the inherited name as well
327

328                     if( kind.startsWith( "type" ) )
329                     {
330                         if( logger.isDebugEnabled() )
331                             logger.debug( "- NameTable.inherit type from: " + key );
332
333                         TypeSpec t =
334                             TypeMap.map( anc + key.substring( key.lastIndexOf( '.' ) ) );
335
336                         // t can be null for some cases where we had to put
337
// Java type names (e.g. for sequence s) into the
338
// name table. These need not be typedef'd again here
339

340                         if( t != null )
341                         {
342                             TypeMap.typedef( name +
343                                     key.substring( key.lastIndexOf( '.' ) ), t );
344                         }
345                         shadowNames.put( name + key.substring( key.lastIndexOf( '.' ) ), kind );
346                     }
347                     else if( kind.equals( "operation" ) )
348                     {
349                         if( logger.isDebugEnabled() )
350                             logger.debug( "- NameTable.inherit operation from: " +
351                                                            key );
352
353                         NameTable.defineInheritedOperation( name +
354                                                             key.substring( key.lastIndexOf( '.' ) ),
355                                                             anc );
356                     }
357
358                     if( !isDefined( key ) )
359                         throw new RuntimeException JavaDoc( "CompilerError!" );
360                 }
361             }
362         }
363
364         /* update the hashtable */
365
366         try
367         {
368             defineShadows( shadowNames );
369         }
370         catch( NameAlreadyDefined nad )
371         {
372             if( logger.isDebugEnabled() )
373                 logger.debug( "Exception ", nad );
374         }
375     }
376
377     /**
378      * check whether name is already defined
379      */

380
381     public static boolean isDefined( String JavaDoc name )
382     {
383         return ( h.containsKey( name ) );
384     }
385
386     public static boolean isDefined( String JavaDoc name, String JavaDoc kind )
387     {
388         if( !h.containsKey( name ) )
389         {
390             return false;
391         }
392         String JavaDoc k = (String JavaDoc)h.get( name );
393         return ( k.compareTo( kind ) == 0 );
394     }
395
396
397     static boolean baseType( String JavaDoc _s )
398     {
399         return ( _s.equals( "int" ) || _s.equals( "short" ) || _s.equals( "long" ) ||
400                 _s.equals( "float" ) || _s.equals( "boolean" ) ||
401                 _s.equals( "double" ) || _s.equals( "byte" ) || _s.equals( "char" ) ||
402                 _s.equals( "void" ) || _s.equals( "org.omg.CORBA.Object" ) ||
403                 _s.equals( "org.omg.CORBA.Any" ) || _s.equals( "<anon>" ) );
404     }
405 }
406
Popular Tags