package org.jacorb.idl;
/*
* JacORB - a free Java ORB
*
* Copyright (C) 1997-2014 Gerald Brose / The JacORB Team.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Base class for all classes of the abstract IDL syntax tree
*
* @author Gerald Brose
*/
public class IdlSymbol
extends org.jacorb.idl.runtime.symbol
{
private static int num = 10000;
public String pack_name = "";
String name = "";
protected boolean is_pseudo = false; // is this a PIDL spec.?
protected boolean included = false;
protected boolean inhibitionFlag = false;
str_token token;
protected String _id;
private String _version;
protected IdlSymbol enclosing_symbol;
protected String omg_package_prefix = "";
private HashSet<String> imports = new HashSet<String>();
String typeName;
protected static final char fileSeparator =
System.getProperty( "file.separator" ).charAt( 0 );
Logger logger;
/** the posizion in the IDL file where this symbol was found by the lexer,
needed for better error messages */
PositionInfo myPosition = null;
/**
* class constructor
*/
public IdlSymbol( int num )
{
super( num );
inhibitionFlag = parser.getInhibitionState();
logger = parser.getLogger();
myPosition = lexer.getPosition();
}
/**
* used by the lexer to mark this symbol as included from another
* IDL file
*/
void set_included( boolean i )
{
included = i;
}
/**
* is this a symbol included from another IDL file?
* Used to determine if code should be generated or not.
*/
public boolean is_included()
{
return included;
}
/**
*
*/
public void set_pseudo()
{
is_pseudo = true;
}
/**
* is this a PIDL symbol?
*/
public boolean is_pseudo()
{
return is_pseudo;
}
public void set_token( str_token i )
{
token = i;
if( token != null )
{
if( token.pragma_prefix.equals( "omg.org" ) )
{
omg_package_prefix = "org.omg.";
}
set_name( token.str_val );
}
}
public str_token get_token()
{
return token;
}
/**
* get this symbol's name
*/
public String name()
{
return name;
}
/**
* A number of IDL constructs need to have their names
* checked for clashes with name reserved by Java or
* the Java Language Mapping.
*/
public void escapeName()
{
if( !isEscaped() &&
// Not escaping Messaging.ExceptionHolder
!pack_name.startsWith( "org.omg.Messaging" ) &&
lexer.strictJavaEscapeCheck( name ) )
{
if(name.indexOf('.') > 0)
parser.logger.log(Level.WARNING, "Dots within a simple name!");
name = "_" + name;
}
}
private boolean isEscaped()
{
return name().startsWith( "_" );
}
public String deEscapeName()
{
String tmp = name();
if( tmp.startsWith( "_" ) )
{
tmp = tmp.substring( 1 );
}
return tmp;
}
public void setPackage( String s )
{
s = parser.pack_replace( s );
if( pack_name.length() > 0 )
pack_name = s + "." + pack_name;
else
pack_name = s;
}
public void setEnclosingSymbol( IdlSymbol s )
{
if( enclosing_symbol != null && enclosing_symbol != s )
throw new RuntimeException( "Compiler Error: trying to reassign container for " +
name );
enclosing_symbol = s;
}
public IdlSymbol getEnclosingSymbol()
{
return enclosing_symbol;
}
public static int new_num()
{
return num++;
}
/** the name of this symbol */
public void set_name( String n )
{
name = n;
}
/**
* @return fully scoped IDL identifier
*/
String full_name()
{
if( name.length() == 0 )
{
return null;
}
if( pack_name.length() > 0 )
{
return pack_name + "." + name;
}
return name;
}
/**
* @return fully scoped Java identifier, only used in
* code generation phase
*/
String javaName()
{
if( name.length() == 0 )
return null;
if( pack_name.length() > 0 )
{
if( !pack_name.startsWith( "org.omg" ) )
{
return omg_package_prefix + pack_name + "." + name;
}
return pack_name + "." + name;
}
return name;
}
/**
* @return "org.omg." if the symbol has been declared inside a
* scope with a pragma prefix of "omg.org".
*/
public String omgPrefix()
{
return omg_package_prefix;
}
/** empty parse */
public void parse()
throws ParseException
{
}
public void print( PrintWriter ps )
{
throw new java.lang.RuntimeException( "--abstract--!" );
}
public void printImport( PrintWriter ps )
{
if( !pack_name.equals( "" ) )
{
Iterator i = imports.iterator ();
while (i.hasNext ())
{
String name = (String)i.next();
ps.println( "import " + name + ";" );
}
ps.println();
}
}
/**
* Called by derived classes to potentially add the aliasHelper
* name to the generated Java class's import list, which is
* necessary in case the mapped code is in the unnamed package.
*
* @param alias the name of the alias
*/
public void addImportedAlias( String alias )
{
if( parser.logger.isLoggable(Level.ALL) )
parser.logger.log(Level.ALL, "addImportedAlias " + alias);
if( alias.indexOf( '.' ) < 0 && !BaseType.isBasicName( alias ) )
{
imports.add( alias + "Helper");
}
}
/**
* Called by derived classes to potentially add the name and the
* nameHelper to the generated Java class's import list, which is
* necessary in case the mapped code is in the unnamed package.
*
* @param name
*/
public void addImportedName( String name )
{
// Ensure that we strip [] from names.
if ( name != null && name.endsWith( "[]" ) )
{
name = name.substring( 0, name.length() - 2 );
}
// Only enter this if its an alias.
if( name != null && name.indexOf( '.' ) < 0 && !BaseType.isBasicName( name ) )
{
addImportedName( name, null );
}
}
/**
* Called by derived classes to potentially add the name and the
* nameHelper to the generated Java class's import list, which is
* necessary in case the mapped code is in the unnamed package.
*
* @param name
* @param type
*/
public void addImportedName( String name, TypeSpec type )
{
if( name != null && name.indexOf( '.' ) < 0 && !BaseType.isBasicName( name ) )
{
if( parser.logger.isLoggable(Level.ALL) )
parser.logger.log(Level.ALL, "addImportedName " + name);
// If we have a typedef for a basic type we only want
// to import the helper class.
if( ( type == null ) || !BaseType.isBasicName( type.toString() ) )
{
imports.add( name );
}
imports.add( name + "Helper" );
}
}
/**
* Called by derived classes to potentially add the name, the
* nameHelper and nameHolder to the generated Java class's import
* list, which is necessary in case the mapped code is in the
* unnamed package.
*
* @param name
*/
public void addImportedNameHolder( String name )
{
if( name.indexOf( '.' ) < 0 && !BaseType.isBasicName( name ) )
{
if( parser.logger.isLoggable(Level.ALL) )
parser.logger.log(Level.ALL, "addImportedNameHolder " + name);
imports.add( name );
}
}
public void setPrintPhaseNames()
{
if( pack_name.length() > 0 )
{
typeName = ScopedName.unPseudoName( pack_name + "." + name );
if( !typeName.startsWith( "org.omg" ) )
{
typeName = omg_package_prefix + typeName;
}
pack_name = typeName.substring( 0, typeName.lastIndexOf( "." ) );
}
else
{
typeName = ScopedName.unPseudoName( name );
}
if( parser.logger.isLoggable(Level.ALL) )
{
parser.logger.log(Level.ALL, "setPrintPhaseNames: pack_name " +
pack_name + ", name " + name +
" typename " + typeName);
}
}
public void printIdMethod( PrintWriter ps )
{
ps.println( "\tpublic static String id()" );
ps.println( "\t{" );
ps.println( "\t\treturn \"" + id() + "\";" );
ps.println( "\t}" );
}
/**
* @return this symbol's repository Id
*/
public String id()
{
IdlSymbol enc = enclosing_symbol;
StringBuffer sb = new StringBuffer();
ScopeData sd = null;
str_token enctoken = null;
if( parser.logger.isLoggable(Level.ALL) )
parser.logger.log(Level.ALL, "Id for name " + name);
if( _id == null )
{
do
{
if (enc != null)
{
// Get enclosing token and check idMap then, if not in
// there, determine prefix manually.
enctoken = enc.get_token();
if (enc instanceof Scope)
{
sd = ((Scope)enc).getScopeData ();
if (sd == null)
{
org.jacorb.idl.parser.fatal_error
(
"ScopeDate null for " + name + " " +
this.getClass().getName(), null
);
}
}
if (sd != null && sd.idMap.get (name) != null)
{
_id = (String)sd.idMap.get (name);
break;
}
// Not had a #pragma prefix, attempt to determine using prefix
// Slightly horrible...this says 'if the current token prefix
// is blank' then use the enclosing tokens prefix OR
// if the current token has a matching prefix to the parent
// then also do this (this prevents:
// prefix Foo
// module F {
// prefix X
// interface Y {}
// }
if (token != null &&
(
"".equals (token.pragma_prefix) ||
enctoken.pragma_prefix.equals (token.pragma_prefix)
))
{
String enclosingName = enc.name;
// if the enclosing symbol is a module, its name
// is a package name and might have been modified
// by the -i2jpackage switch. We want its unchanged
// name as part of the RepositoryId, however.
if( enc instanceof Module )
{
String enclosingModuleName =
((Module)enc).originalModuleName ();
if ( !enclosingModuleName.startsWith ("org"))
{
enclosingName = ((Module)enc).originalModuleName ();
}
// remove leading "_" in repository Ids
if( enc.isEscaped ())
{
enclosingName = enclosingName.substring (1);
}
}
sb.insert (0, enclosingName + "/");
enc = enc.getEnclosingSymbol ();
}
else
{
break;
}
}
// Global Scope
else if (parser.scopes.size () == 1 &&
parser.currentScopeData ().idMap.get (name) != null)
{
_id = (String)parser.currentScopeData ().idMap.get (name);
break;
}
else
{
// This is global scope - there is no enclosing symbol and no
// defining #pragma. The ID can be built simply from the name
break;
}
}
while (enc != null);
if (_id == null)
{
// There was no #pragma.
if( isEscaped() )
{
sb.append( name.substring( 1 ) );
}
else
{
sb.append( name );
}
String typePrefix = this.getPrefix();
if( token != null && token.pragma_prefix.length() > 0 ||
typePrefix != null)
{
_id =
(
"IDL:" + (typePrefix != null ? typePrefix : token.pragma_prefix) +
"/" + sb.toString().replace( '.', '/' ) + ":" + version ()
);
}
else
{
_id = "IDL:" + sb.toString().replace( '.', '/' ) + ":" + version();
}
}
}
if( parser.logger.isLoggable(Level.ALL) )
{
parser.logger.log(Level.ALL, "Id for name " + name + " is " + _id);
}
return _id;
}
/**
* Gets prefix which was set by "typeprefix"
*
* @return Returns null if typeprefix undefined
*/
private String getPrefix()
{
//check directly defined typeprefix for this module
String prefix = TypePrefixes.getDefined(this.pack_name);
if(prefix != null)
{
return prefix;
}
//calculate inherited prefix from parent modules
int len = Integer.MAX_VALUE;
for(Iterator i = TypePrefixes.getTypePrefixes().entrySet().iterator() ; i.hasNext();)
{
Entry e = (Entry)i.next();
String pack_name = (String)e.getKey();
if(this.pack_name.startsWith(pack_name))
{
int tempLen = this.pack_name.length() - pack_name.length();
if(len > this.pack_name.length() - pack_name.length())
{
len = tempLen;
prefix = (String)e.getValue();
}
}
}
return prefix;
}
private String version()
{
IdlSymbol enc = this;
String tmp;
if( _version == null )
{
while( true )
{
while( enc != null && !( enc instanceof Scope ) )
{
enc = enc.getEnclosingSymbol();
}
if( enc != null )
{
ScopeData sd = ( (Scope)enc ).getScopeData();
if( sd == null )
{
org.jacorb.idl.parser.fatal_error( "ScopeData null for " + name + " " +
this.getClass().getName(), null );
}
Hashtable h = sd.versionMap;
// check for version settings in this scope
tmp = (String)h.get( name );
if( tmp != null )
{
_version = tmp;
break;
}
enc = enc.getEnclosingSymbol();
}
// Global Scope
else if (parser.scopes.size () == 1 &&
parser.currentScopeData ().versionMap.get (name) != null)
{
_version = (String)parser.currentScopeData ().versionMap.get (name);
break;
}
else
{
_version = "1.0";
break;
}
}
// check for further versions (which would be an error!)
if( enc != null )
enc = enc.getEnclosingSymbol();
while( true )
{
while( enc != null && !( enc instanceof Scope ) )
{
enc = enc.getEnclosingSymbol();
}
if( enc != null )
{
// check for version settings in this scope
Hashtable h = ( (Scope)enc ).getScopeData().versionMap;
tmp = (String)h.get( name );
if( tmp != null )
{
lexer.emit_error( "Version for " + name +
" already declared!", enc.get_token() );
break;
}
enc = enc.getEnclosingSymbol();
}
else
{
break;
}
}
}
return _version;
}
/**
* access to parser state (e.g. options)
*/
protected boolean generateIncluded()
{
return parser.generateIncluded() && !( inhibitionFlag );
}
/**
* this method will prepend the
* specified name with the omg prefix if
* necessary
*
* @return the full qualified java name
*/
protected String getFullName(String name)
{
if (!name.startsWith("org.omg") && !name.startsWith ("java.lang"))
{
return omgPrefix() + name;
}
return name;
}
/**
* let the visitor pattern do its work...
*/
public void accept( IDLTreeVisitor visitor )
{
// nothing here, all work done in subclasses.
}
/**
* <code>printClassComment</code> is used by inherited classes to print
* the class comment.
*
* @param name a <code>String</code> value
* @param ps a <code>PrintWriter</code> value
*/
protected final void printClassComment(String type, String name, PrintWriter ps)
{
ps.println("/**");
ps.println(" * Generated from IDL " + type.trim() + " \"" + name + "\".");
ps.println(" *");
ps.println(" * @author JacORB IDL compiler V " + parser.compiler_version);
if (parser.printVersionTimestamps)
{
ps.println(" * @version generated at " + parser.currentDate);
}
ps.println(" */" + Environment.NL);
}
}