/*
 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.corba.se.impl.presentation.rmi ;

import java.security.AccessController;
import java.security.PrivilegedAction;

import java.lang.reflect.Method;

import java.math.BigInteger;

import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.HashMap;
import java.util.StringTokenizer;

import com.sun.corba.se.spi.presentation.rmi.IDLNameTranslator ;

import com.sun.corba.se.impl.presentation.rmi.IDLType ;
import com.sun.corba.se.impl.presentation.rmi.IDLTypeException ;
import com.sun.corba.se.impl.presentation.rmi.IDLTypesUtil ;
import com.sun.corba.se.impl.orbutil.ObjectUtility ;

/**
 * Bidirectional translator between RMI-IIOP interface methods and
 * and IDL Names.
 */
public class IDLNameTranslatorImpl implements IDLNameTranslator {

    // From CORBA Spec, Table 6 Keywords.
    // Note that since all IDL identifiers are case
    // insensitive, java identifier comparisons to these
    // will be case insensitive also.
    private static String[] IDL_KEYWORDS = {

        "abstract", "any", "attribute", "boolean", "case", "char",
        "const", "context", "custom", "default", "double", "enum",
        "exception", "factory", "FALSE", "fixed", "float", "in", "inout",
        "interface", "long", "module", "native", "Object", "octet",
        "oneway", "out", "private", "public", "raises", "readonly", "sequence",
        "short", "string", "struct", "supports", "switch", "TRUE", "truncatable",
        "typedef", "unsigned", "union", "ValueBase", "valuetype", "void",
        "wchar", "wstring"

    };

    private static char[] HEX_DIGITS = {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        'A', 'B', 'C', 'D', 'E', 'F'
    };

    private static final String UNDERSCORE = "_";

    // used to mangle java inner class names
    private static final String INNER_CLASS_SEPARATOR =
        UNDERSCORE + UNDERSCORE;

    // used to form IDL array type names
    private static final String[] BASE_IDL_ARRAY_MODULE_TYPE=
        new String[] { "org", "omg", "boxedRMI" } ;

    private static final String BASE_IDL_ARRAY_ELEMENT_TYPE = "seq";

    // used to mangling java identifiers that have a leading underscore
    private static final String LEADING_UNDERSCORE_CHAR = "J";
    private static final String ID_CONTAINER_CLASH_CHAR = UNDERSCORE;

    // separator used between types in a mangled overloaded method name
    private static final String OVERLOADED_TYPE_SEPARATOR =
        UNDERSCORE + UNDERSCORE;

    // string appended to attribute if it clashes with a method name
    private static final String ATTRIBUTE_METHOD_CLASH_MANGLE_CHARS =
        UNDERSCORE + UNDERSCORE;

    // strings prepended to the attribute names in order to form their
    // IDL names.
    private static final String GET_ATTRIBUTE_PREFIX = "_get_";
    private static final String SET_ATTRIBUTE_PREFIX = "_set_";
    private static final String IS_ATTRIBUTE_PREFIX  = "_get_";

    private static Set idlKeywords_;

    static {

        idlKeywords_ = new HashSet();
        for(int i = 0; i < IDL_KEYWORDS.length; i++) {
            String next = (String) IDL_KEYWORDS[i];
            // Convert keyword to all caps to ease equality
            // check.
            String keywordAllCaps = next.toUpperCase();
            idlKeywords_.add(keywordAllCaps);
        }

    }

    //
    // Instance state
    //

    // Remote interface for name translation.
    private Class[] interf_;

    // Maps used to hold name translations.  These do not need to be
    // synchronized since the translation is never modified after
    // initialization.
    private Map methodToIDLNameMap_;
    private Map IDLNameToMethodMap_;
    private Method[] methods_;

    /**
     * Return an IDLNameTranslator for the given interface.
     *
     * @throws IllegalStateException if given class is not a valid
     *         RMI/IIOP Remote Interface
     */
    public static IDLNameTranslator get( Class interf )
    {

        return new IDLNameTranslatorImpl(new Class[] { interf } );

    }

    /**
     * Return an IDLNameTranslator for the given interfacex.
     *
     * @throws IllegalStateException if given classes are not  valid
     *         RMI/IIOP Remote Interfaces
     */
    public static IDLNameTranslator get( Class[] interfaces )
    {

        return new IDLNameTranslatorImpl(interfaces );

    }

    public static String getExceptionId( Class cls )
    {
        // Requirements for this method:
        // 1. cls must be an exception but not a RemoteException.
        // 2. If cls has an IDL keyword name, an underscore is prepended (1.3.2.2).
        // 3. If cls jas a leading underscore, J is prepended (1.3.2.3).
        // 4. If cls has an illegal IDL ident char, it is mapped to UXXXX where
        //    XXXX is the unicode value in hex of the char (1.3.2.4).
        // 5. double underscore for inner class (1.3.2.5).
        // 6. The ID is "IDL:" + name with / separators + ":1.0".
        IDLType itype = classToIDLType( cls ) ;
        return itype.getExceptionName() ;
    }

    public Class[] getInterfaces()
    {
        return interf_;
    }

    public Method[] getMethods()
    {
        return methods_ ;
    }

    public Method getMethod( String idlName )
    {
        return (Method) IDLNameToMethodMap_.get(idlName);
    }

    public String getIDLName( Method method )
    {
        return (String) methodToIDLNameMap_.get(method);
    }

    /**
     * Initialize an IDLNameTranslator for the given interface.
     *
     * @throws IllegalStateException if given class is not a valid
     *         RMI/IIOP Remote Interface
     */
    private IDLNameTranslatorImpl(Class[] interfaces)
    {

        SecurityManager s = System.getSecurityManager();
        if (s != null) {
            s.checkPermission(new DynamicAccessPermission("access"));
        }
        try {
            IDLTypesUtil idlTypesUtil = new IDLTypesUtil();
            for (int ctr=0; ctr<interfaces.length; ctr++)
                idlTypesUtil.validateRemoteInterface(interfaces[ctr]);
            interf_ = interfaces;
            buildNameTranslation();
        } catch( IDLTypeException ite) {
            String msg = ite.getMessage();
            IllegalStateException ise = new IllegalStateException(msg);
            ise.initCause(ite);
            throw ise;
        }
    }

    private void buildNameTranslation()
    {
        // holds method info, keyed by method
        Map allMethodInfo = new HashMap() ;

        for (int ctr=0; ctr<interf_.length; ctr++) {
            Class interf = interf_[ctr] ;

            IDLTypesUtil idlTypesUtil = new IDLTypesUtil();
            final Method[] methods = interf.getMethods();
            // Handle the case of a non-public interface!
            AccessController.doPrivileged(new PrivilegedAction() {
                public Object run() {
                    Method.setAccessible( methods, true ) ;
                    return null ;
                }
            } ) ;

            // Take an initial pass through all the methods and create some
            // information that will be used to track the IDL name
            // transformation.
            for(int i = 0; i < methods.length; i++) {

                Method nextMethod = methods[i];

                IDLMethodInfo methodInfo = new IDLMethodInfo();

                methodInfo.method = nextMethod;

                if (idlTypesUtil.isPropertyAccessorMethod(nextMethod, interf)) {
                    methodInfo.isProperty = true;
                    String attributeName = idlTypesUtil.
                        getAttributeNameForProperty(nextMethod.getName());
                    methodInfo.originalName = attributeName;
                    methodInfo.mangledName  = attributeName;
                } else {
                    methodInfo.isProperty = false;
                    methodInfo.originalName = nextMethod.getName();
                    methodInfo.mangledName  = nextMethod.getName();
                }

                allMethodInfo.put(nextMethod, methodInfo);
            }
        }

        //
        // Perform case sensitivity test first.  This applies to all
        // method names AND attributes.  Compare each method name and
        // attribute to all other method names and attributes.  If names
        // differ only in case, apply mangling as defined in section 1.3.2.7
        // of Java2IDL spec.  Note that we compare using the original names.
        //
        for(Iterator outerIter=allMethodInfo.values().iterator();
            outerIter.hasNext();) {
            IDLMethodInfo outer = (IDLMethodInfo) outerIter.next();
            for(Iterator innerIter = allMethodInfo.values().iterator();
                innerIter.hasNext();) {
                IDLMethodInfo inner = (IDLMethodInfo) innerIter.next();

                if( (outer != inner) &&
                    (!outer.originalName.equals(inner.originalName)) &&
                    outer.originalName.equalsIgnoreCase(inner.originalName) ) {
                    outer.mangledName =
                        mangleCaseSensitiveCollision(outer.originalName);
                    break;
                }

            }
        }

        for(Iterator iter = allMethodInfo.values().iterator();
            iter.hasNext();) {
            IDLMethodInfo next = (IDLMethodInfo) iter.next();
            next.mangledName =
                mangleIdentifier(next.mangledName, next.isProperty);
        }

        //
        // Now check for overloaded method names and apply 1.3.2.6.
        //
        for(Iterator outerIter=allMethodInfo.values().iterator();
            outerIter.hasNext();) {
            IDLMethodInfo outer = (IDLMethodInfo) outerIter.next();
            if( outer.isProperty ) {
                continue;
            }
            for(Iterator innerIter = allMethodInfo.values().iterator();
                innerIter.hasNext();) {
                IDLMethodInfo inner = (IDLMethodInfo) innerIter.next();

                if( (outer != inner) &&
                    !inner.isProperty &&
                    outer.originalName.equals(inner.originalName) ) {
                    outer.mangledName = mangleOverloadedMethod
                        (outer.mangledName, outer.method);
                    break;
                }
            }
        }

        //
        // Now mangle any properties that clash with method names.
        //
        for(Iterator outerIter=allMethodInfo.values().iterator();
            outerIter.hasNext();) {
            IDLMethodInfo outer = (IDLMethodInfo) outerIter.next();
            if( !outer.isProperty ) {
                continue;
            }
            for(Iterator innerIter = allMethodInfo.values().iterator();
                innerIter.hasNext();) {
                IDLMethodInfo inner = (IDLMethodInfo) innerIter.next();
                if( (outer != inner) &&
                    !inner.isProperty &&
                    outer.mangledName.equals(inner.mangledName) ) {
                    outer.mangledName = outer.mangledName +
                        ATTRIBUTE_METHOD_CLASH_MANGLE_CHARS;
                    break;
                }
            }
        }

        //
        // Ensure that no mapped method names clash with mapped name
        // of container(1.3.2.9).  This is a case insensitive comparison.
        //
        for (int ctr=0; ctr<interf_.length; ctr++ ) {
            Class interf = interf_[ctr] ;
            String mappedContainerName = getMappedContainerName(interf);
            for(Iterator iter = allMethodInfo.values().iterator();
                iter.hasNext();) {
                IDLMethodInfo next = (IDLMethodInfo) iter.next();
                if( !next.isProperty &&
                    identifierClashesWithContainer(mappedContainerName,
                                                   next.mangledName)) {
                    next.mangledName = mangleContainerClash(next.mangledName);
                }
            }
        }

        //
        // Populate name translation maps.
        //
        methodToIDLNameMap_ = new HashMap();
        IDLNameToMethodMap_ = new HashMap();
        methods_ = (Method[])allMethodInfo.keySet().toArray(
            new Method[0] ) ;

        for(Iterator iter = allMethodInfo.values().iterator();
            iter.hasNext();) {
            IDLMethodInfo next = (IDLMethodInfo) iter.next();
            String idlName = next.mangledName;
            if( next.isProperty ) {
                String origMethodName = next.method.getName();
                String prefix = "";

                if( origMethodName.startsWith("get") ) {
                    prefix = GET_ATTRIBUTE_PREFIX;
                } else if( origMethodName.startsWith("set") ) {
                    prefix = SET_ATTRIBUTE_PREFIX;
                } else {
                    prefix = IS_ATTRIBUTE_PREFIX;
                }

                idlName = prefix + next.mangledName;
            }

            methodToIDLNameMap_.put(next.method, idlName);

            // Final check to see if there are any clashes after all the
            // manglings have been applied.  If so, this is treated as an
            // invalid interface.  Currently, we do a CASE-SENSITIVE
            // comparison since that matches the rmic behavior.
            // @@@ Shouldn't this be a case-insensitive check?
            if( IDLNameToMethodMap_.containsKey(idlName) ) {
                // @@@ I18N
                Method clash = (Method) IDLNameToMethodMap_.get(idlName);
                throw new IllegalStateException("Error : methods " +
                    clash + " and " + next.method +
                    " both result in IDL name '" + idlName + "'");
            } else {
                IDLNameToMethodMap_.put(idlName, next.method);
            }
        }

        return;

    }


    /**
     * Perform all necessary stand-alone identifier mangling operations
     * on a java identifier that is being transformed into an IDL name.
     * That is, mangling operations that don't require looking at anything
     * else but the identifier itself.  This covers sections 1.3.2.2, 1.3.2.3,
     * and 1.3.2.4 of the Java2IDL spec.  Method overloading and
     * case-sensitivity checks are handled elsewhere.
     */

    private static String mangleIdentifier(String identifier) {
        return mangleIdentifier(identifier, false);
    }

    private static String mangleIdentifier(String identifier, boolean attribute) {

        String mangledName = identifier;

        //
        // Apply leading underscore test (1.3.2.3)
        // This should be done before IDL Keyword clash test, since clashing
        // IDL keywords are mangled by adding a leading underscore.
        //
        if( hasLeadingUnderscore(mangledName) ) {
            mangledName = mangleLeadingUnderscore(mangledName);
        }

        //
        // Apply IDL keyword clash test (1.3.2.2).
        // This is not needed for attributes since when the full property
        // name is composed it cannot clash with an IDL keyword.
        // (Also, rmic doesn't do it.)
        //

        if( !attribute && isIDLKeyword(mangledName) ) {
            mangledName = mangleIDLKeywordClash(mangledName);
        }

        //
        // Replace illegal IDL identifier characters (1.3.2.4)
        // for all method names and attributes.
        //
        if( !isIDLIdentifier(mangledName) ) {
            mangledName = mangleUnicodeChars(mangledName);
        }

        return mangledName;
    }

    // isIDLKeyword and mangleIDLKeywordClash are exposed here so that
    // IDLType can use them.
    //
    // XXX refactoring needed:
    // 1. Split off isIDLKeywork and mangleIDLKeywordClash (and possibly
    //    other methods) into a utility class.
    // 2. Move all of classToIDLType to a constructor inside IDLType.
    //
    // The problem appears to be that we need all of the code that
    // performs various checks for name problems and the corresponding
    // fixes into a utility class.  Then we need to see what other
    // refactorings present themselves.

    /**
     * Checks whether a java identifier clashes with an
     * IDL keyword.  Note that this is a case-insensitive
     * comparison.
     *
     * Used to implement section 1.3.2.2 of Java2IDL spec.
     */
    static boolean isIDLKeyword(String identifier) {

        String identifierAllCaps = identifier.toUpperCase();

        return idlKeywords_.contains(identifierAllCaps);
    }

    static String mangleIDLKeywordClash(String identifier) {
        return UNDERSCORE + identifier;
    }

    private static String mangleLeadingUnderscore(String identifier) {
        return LEADING_UNDERSCORE_CHAR + identifier;
    }

    /**
     * Checks whether a java identifier starts with an underscore.
     * Used to implement section 1.3.2.3 of Java2IDL spec.
     */
    private static boolean hasLeadingUnderscore(String identifier) {
        return identifier.startsWith(UNDERSCORE);
    }

    /**
     * Implements Section 1.3.2.4 of Java2IDL Mapping.
     * All non-IDL identifier characters must be replaced
     * with their Unicode representation.
     */
    static String mangleUnicodeChars(String identifier) {
        StringBuffer mangledIdentifier = new StringBuffer();

        for(int i = 0; i < identifier.length(); i++) {
            char nextChar = identifier.charAt(i);
            if( isIDLIdentifierChar(nextChar) ) {
                mangledIdentifier.append(nextChar);
            } else {
                String unicode = charToUnicodeRepresentation(nextChar);
                mangledIdentifier.append(unicode);
            }
        }

        return mangledIdentifier.toString();
    }

    /**
     * Implements mangling portion of Section 1.3.2.7 of Java2IDL spec.
     * This method only deals with the actual mangling.  Decision about
     * whether case-sensitive collision mangling is required is made
     * elsewhere.
     *
     *
     * "...a mangled name is generated consisting of the original name
     * followed by an underscore separated list of decimal indices
     * into the string, where the indices identify all the upper case
     * characters in the original string. Indices are zero based."
     *
     */
    String mangleCaseSensitiveCollision(String identifier) {

        StringBuffer mangledIdentifier = new StringBuffer(identifier);

        // There is always at least one trailing underscore, whether or
        // not the identifier has uppercase letters.
        mangledIdentifier.append(UNDERSCORE);

        boolean needUnderscore = false;
        for(int i = 0; i < identifier.length(); i++) {
            char next = identifier.charAt(i);
            if( Character.isUpperCase(next) ) {
                // This bit of logic is needed to ensure that we have
                // an underscore separated list of indices but no
                // trailing underscores.  Basically, after we have at least
                // one uppercase letter, we always put an undercore before
                // printing the next one.
                if( needUnderscore ) {
                    mangledIdentifier.append(UNDERSCORE);
                }
                mangledIdentifier.append(i);
                needUnderscore = true;
            }
        }

        return mangledIdentifier.toString();
    }

    private static String mangleContainerClash(String identifier) {
        return identifier + ID_CONTAINER_CLASH_CHAR;
    }

    /**
     * Implements Section 1.3.2.9 of Java2IDL Mapping. Container in this
     * context means the name of the java Class(excluding package) in which
     * the identifier is defined.  Comparison is case-insensitive.
     */
    private static boolean identifierClashesWithContainer
        (String mappedContainerName, String identifier) {

        return identifier.equalsIgnoreCase(mappedContainerName);
    }

    /**
     * Returns Unicode mangling as defined in Section 1.3.2.4 of
     * Java2IDL spec.
     *
     * "For Java identifiers that contain illegal OMG IDL identifier
     * characters such as '$' or Unicode characters outside of ISO Latin 1,
     * any such illegal characters are replaced by "U" followed by the
     * 4 hexadecimal characters(in upper case) representing the Unicode
     * value.  So, the Java name a$b is mapped to aU0024b and
     * x\u03bCy is mapped to xU03BCy."
     */
    public static String charToUnicodeRepresentation(char c) {

        int orig = (int) c;
        StringBuffer hexString = new StringBuffer();

        int value = orig;

        while( value > 0 ) {
            int div = value / 16;
            int mod = value % 16;
            hexString.insert(0, HEX_DIGITS[mod]);
            value = div;
        }

        int numZerosToAdd = 4 - hexString.length();
        for(int i = 0; i < numZerosToAdd; i++) {
            hexString.insert(0, "0");
        }

        hexString.insert(0, "U");
        return hexString.toString();
    }

    private static boolean isIDLIdentifier(String identifier) {

        boolean isIdentifier = true;

        for(int i = 0; i < identifier.length(); i++) {
            char nextChar = identifier.charAt(i);
            // 1st char must be alphbetic.
            isIdentifier  = (i == 0) ?
                isIDLAlphabeticChar(nextChar) :
                isIDLIdentifierChar(nextChar);
            if( !isIdentifier ) {
                break;
            }
        }

        return isIdentifier;

    }

    private static boolean isIDLIdentifierChar(char c) {
        return (isIDLAlphabeticChar(c) ||
                isIDLDecimalDigit(c)   ||
                isUnderscore(c));
    }

    /**
     * True if character is one of 114 Alphabetic characters as
     * specified in Table 2 of Chapter 3 in CORBA spec.
     */
    private static boolean isIDLAlphabeticChar(char c) {

        // NOTE that we can't use the java.lang.Character
        // isUpperCase, isLowerCase, etc. methods since they
        // include many characters other than the Alphabetic list in
        // the CORBA spec.  Instead, we test for inclusion in the
        // Unicode value ranges for the corresponding legal characters.

        boolean alphaChar =
            (
             // A - Z
             ((c >= 0x0041) && (c <= 0x005A))

             ||

             // a - z
             ((c >= 0x0061) && (c <= 0x007A))

             ||

             // other letter uppercase, other letter lowercase, which is
             // the entire upper half of C1 Controls except X and /
             ((c >= 0x00C0) && (c <= 0x00FF)
              && (c != 0x00D7) && (c != 0x00F7)));

        return alphaChar;
    }

    /**
     * True if character is one of 10 Decimal Digits
     * specified in Table 3 of Chapter 3 in CORBA spec.
     */
    private static boolean isIDLDecimalDigit(char c) {
        return ( (c >= 0x0030) && (c <= 0x0039) );
    }

    private static boolean isUnderscore(char c) {
        return ( c == 0x005F );
    }

    /**
     * Mangle an overloaded method name as defined in Section 1.3.2.6 of
     * Java2IDL spec.  Current value of method name is passed in as argument.
     * We can't start from original method name since the name might have
     * been partially mangled as a result of the other rules.
     */
    private static String mangleOverloadedMethod(String mangledName, Method m) {

        IDLTypesUtil idlTypesUtil = new IDLTypesUtil();

        // Start by appending the separator string
        String newMangledName = mangledName + OVERLOADED_TYPE_SEPARATOR;

        Class[] parameterTypes = m.getParameterTypes();

        for(int i = 0; i < parameterTypes.length; i++) {
            Class nextParamType = parameterTypes[i];

            if( i > 0 ) {
                newMangledName = newMangledName + OVERLOADED_TYPE_SEPARATOR;
            }
            IDLType idlType = classToIDLType(nextParamType);

            String moduleName = idlType.getModuleName();
            String memberName = idlType.getMemberName();

            String typeName = (moduleName.length() > 0) ?
                moduleName + UNDERSCORE + memberName : memberName;

            if( !idlTypesUtil.isPrimitive(nextParamType) &&
                (idlTypesUtil.getSpecialCaseIDLTypeMapping(nextParamType)
                 == null) &&
                isIDLKeyword(typeName) ) {
                typeName = mangleIDLKeywordClash(typeName);
            }

            typeName = mangleUnicodeChars(typeName);

            newMangledName = newMangledName + typeName;
        }

        return newMangledName;
    }


    private static IDLType classToIDLType(Class c) {

        IDLType idlType = null;
        IDLTypesUtil idlTypesUtil = new IDLTypesUtil();

        if( idlTypesUtil.isPrimitive(c) ) {

            idlType = idlTypesUtil.getPrimitiveIDLTypeMapping(c);

        } else if( c.isArray() ) {

            // Calculate array depth, as well as base element type.
            Class componentType = c.getComponentType();
            int numArrayDimensions = 1;
            while(componentType.isArray()) {
                componentType = componentType.getComponentType();
                numArrayDimensions++;
            }
            IDLType componentIdlType = classToIDLType(componentType);

            String[] modules = BASE_IDL_ARRAY_MODULE_TYPE;
            if( componentIdlType.hasModule() ) {
                modules = (String[])ObjectUtility.concatenateArrays( modules,
                    componentIdlType.getModules() ) ;
            }

            String memberName = BASE_IDL_ARRAY_ELEMENT_TYPE +
                numArrayDimensions + UNDERSCORE +
                componentIdlType.getMemberName();

            idlType = new IDLType(c, modules, memberName);

        } else {
            idlType = idlTypesUtil.getSpecialCaseIDLTypeMapping(c);

            if (idlType == null) {
                // Section 1.3.2.5 of Java2IDL spec defines mangling rules for
                // inner classes.
                String memberName = getUnmappedContainerName(c);

                // replace inner class separator with double underscore
                memberName = memberName.replaceAll("\\$",
                                                   INNER_CLASS_SEPARATOR);

                if( hasLeadingUnderscore(memberName) ) {
                    memberName = mangleLeadingUnderscore(memberName);
                }

                // Get raw package name.  If there is a package, it
                // will still have the "." separators and none of the
                // mangling rules will have been applied.
                String packageName = getPackageName(c);

                if (packageName == null) {
                    idlType = new IDLType( c, memberName ) ;
                } else {
                    // If this is a generated IDL Entity Type we need to
                    // prepend org_omg_boxedIDL per sections 1.3.5 and 1.3.9
                    if (idlTypesUtil.isEntity(c)) {
                        packageName = "org.omg.boxedIDL." + packageName ;
                    }

                    // Section 1.3.2.1 and 1.3.2.6 of Java2IDL spec defines
                    // rules for mapping java packages to IDL modules and for
                    // mangling module name portion of type name.  NOTE that
                    // of the individual identifier mangling rules,
                    // only the leading underscore test is done here.
                    // The other two(IDL Keyword, Illegal Unicode chars) are
                    // done in mangleOverloadedMethodName.
                    StringTokenizer tokenizer =
                        new StringTokenizer(packageName, ".");

                    String[] modules = new String[ tokenizer.countTokens() ] ;
                    int index = 0 ;
                    while (tokenizer.hasMoreElements()) {
                        String next = tokenizer.nextToken();
                        String moreMangled = hasLeadingUnderscore( next ) ?
                            mangleLeadingUnderscore( next ) : next;

                        modules[index++] = moreMangled ;
                    }

                    idlType = new IDLType(c, modules, memberName);
                }
            }
        }

        return idlType;
    }

    /**
     * Return Class' package name or null if there is no package.
     */
    private static String getPackageName(Class c) {
        Package thePackage = c.getPackage();
        String packageName = null;

        // Try to get package name by introspection.  Some classloaders might
        // not provide this information, so check for null.
        if( thePackage != null ) {
            packageName = thePackage.getName();
        } else {
            // brute force method
            String fullyQualifiedClassName = c.getName();
            int lastDot = fullyQualifiedClassName.indexOf('.');
            packageName = (lastDot == -1) ? null :
                fullyQualifiedClassName.substring(0, lastDot);
        }
        return packageName;
    }

    private static String getMappedContainerName(Class c) {
        String unmappedName = getUnmappedContainerName(c);

        return mangleIdentifier(unmappedName);
    }

    /**
     * Return portion of class name excluding package name.
     */
    private static String getUnmappedContainerName(Class c) {

        String memberName  = null;
        String packageName = getPackageName(c);

        String fullyQualifiedClassName = c.getName();

        if( packageName != null ) {
            int packageLength = packageName.length();
            memberName = fullyQualifiedClassName.substring(packageLength + 1);
        } else {
            memberName = fullyQualifiedClassName;

        }

        return memberName;
    }

    /**
     * Internal helper class for tracking information related to each
     * interface method while we're building the name translation table.
     */
    private static class IDLMethodInfo
    {
        public Method method;
        public boolean isProperty;

        // If this is a property, originalName holds the original
        // attribute name. Otherwise, it holds the original method name.
        public String originalName;

        // If this is a property, mangledName holds the mangled attribute
        // name. Otherwise, it holds the mangled method name.
        public String mangledName;

    }

    public String toString() {

        StringBuffer contents = new StringBuffer();
        contents.append("IDLNameTranslator[" );
        for( int ctr=0; ctr<interf_.length; ctr++) {
            if (ctr != 0)
                contents.append( " " ) ;
            contents.append( interf_[ctr].getName() ) ;
        }
        contents.append("]\n");
        for(Iterator iter = methodToIDLNameMap_.keySet().iterator();
            iter.hasNext();) {

            Method method  = (Method) iter.next();
            String idlName = (String) methodToIDLNameMap_.get(method);

            contents.append(idlName + ":" + method + "\n");

        }

        return contents.toString();
    }
}
