protected void resolveNameClashes()

in axis-codegen/src/main/java/org/apache/axis/wsdl/toJava/JavaGeneratorFactory.java [973:1222]


    protected void resolveNameClashes(SymbolTable symbolTable) {

        // Keep a list of anonymous types so we don't try to resolve them twice.
        HashSet anonTypes = new HashSet();
        List collisionCandidates = new ArrayList();      // List of vector of SymbolTable entry
        
        List localParts = new ArrayList();      // all localparts in all symboltable entries        
        for (Iterator i = symbolTable.getHashMap().keySet().iterator(); i.hasNext(); ) {
            QName qName = (QName)i.next();
            String localPart = qName.getLocalPart();
            if (!localParts.contains(localPart))
                localParts.add(localPart);
        }
            
        Map pkg2NamespacesMap = emitter.getNamespaces().getPkg2NamespacesMap();
        for (Iterator i = pkg2NamespacesMap.values().iterator(); i.hasNext(); ) {            
            Vector namespaces = (Vector)i.next();  // namepaces mapped to same package
                    
            // Combine entry vectors, which have the same entry name, into a new entry vector.
            for (int j = 0; j < localParts.size(); j++) {
                Vector v = new Vector();
                for (int k = 0; k < namespaces.size(); k++) {
                    QName qName = new QName((String)namespaces.get(k), (String)localParts.get(j));
                    if (symbolTable.getHashMap().get(qName) != null) {
                        v.addAll((Vector)symbolTable.getHashMap().get(qName));
                    }
                }
                if(v.size()>0) {
                    collisionCandidates.add(v);
                }
            }
        }
        Iterator it = collisionCandidates.iterator();
        
        while (it.hasNext()) {
            Vector v = new Vector(
                    (Vector) it.next());    // New vector we can temporarily add to it
          
            // Remove MessageEntries since they are not mapped
            int index = 0;

            while (index < v.size()) {
                if (v.elementAt(index) instanceof MessageEntry) {
                    // Need to resolve a Exception message.
                    MessageEntry msgEntry = (MessageEntry) v.elementAt(index);                    
                    // AXIS-2900: Only simple type faults generate additional classes; message entries for
                    // complex type faults don't cause any collisions.
                    if (Utils.isFaultComplex(msgEntry) || msgEntry.getDynamicVar(EXCEPTION_CLASS_NAME) == null) {
                        v.removeElementAt(index);
                    } else {                        
                        index++;
                    }
                } else {
                    index++;
                }
            }

            if (v.size() > 1) {
                boolean resolve = true;

                // Common Special Case:
                // If a Type and Element have the same QName, and the Element
                // references the Type, then they are the same class so
                // don't bother mangling.
                if (v.size() == 2 &&
                    ((v.elementAt(0) instanceof Element &&
                      v.elementAt(1) instanceof Type) ||
                     (v.elementAt(1) instanceof Element &&
                      v.elementAt(0) instanceof Type))) {
                    Element e;
                    Type t;
                    if (v.elementAt(0) instanceof Element) {
                        e = (Element) v.elementAt(0);
                        t = (Type) v.elementAt(1);
                    } else {
                        e = (Element) v.elementAt(1);
                        t = (Type) v.elementAt(0);
                    }

                    BooleanHolder forElement = new BooleanHolder();
                    QName eType = Utils.getTypeQName(e.getNode(),
                            forElement, false);

                    if ((eType != null) && !forElement.value && eType.equals(t.getQName())) {
                        resolve = false;
                    }
                }

                // Other Special Case:
                // If the names are already different, no mangling is needed.
                if (resolve) {
                    resolve = false;           // Assume false

                    String name = null;

                    for (int i = 0; (i < v.size()) && !resolve; ++i) {
                        SymTabEntry entry = (SymTabEntry) v.elementAt(i);

                        if ((entry instanceof MessageEntry)
                                || (entry instanceof BindingEntry)) {                            
                            // Need to resolve a exception class name                            
                            String exceptionClassName = (String) entry.getDynamicVar(EXCEPTION_CLASS_NAME);
                            if (exceptionClassName != null) {                                
                                if (name == null) {
                                    name = exceptionClassName;
                                } else if (name.equals(exceptionClassName)) {
                                    resolve = true;
                                }
                            }
                        } else if (name == null) {
                            name = entry.getName();
                        } else if (name.equals(entry.getName())) {
                            resolve = true;    // Need to do resolution
                        }
                    }
                }

                // Full Mangle if resolution is necessary.
                if (resolve) {
                    boolean firstType = true;

                    for (int i = 0; i < v.size(); ++i) {
                        SymTabEntry entry = (SymTabEntry) v.elementAt(i);

                        if (entry instanceof Element) {
                            mangleName(entry, ELEMENT_SUFFIX);

                            // If this global element was defined using
                            // an anonymous type, then need to change the
                            // java name of the anonymous type to match.
                            QName anonQName =
                                    new QName(entry.getQName().getNamespaceURI(),
                                            SymbolTable.ANON_TOKEN
                                    + entry.getQName().getLocalPart());
                            
                            TypeEntry anonType =
                                    symbolTable.getType(anonQName);

                            if (anonType != null) {
                                anonType.setName(entry.getName());
                                anonTypes.add(anonType);
                            }                            
                        } else if (entry instanceof TypeEntry) {

                            // Search all other types for java names that match this one.
                            // The sameJavaClass method returns true if the java names are
                            // the same (ignores [] ).
                            if (firstType) {
                                firstType = false;

                                Iterator types =
                                        symbolTable.getTypeIndex().values().iterator();

                                while (types.hasNext()) {
                                    TypeEntry type = (TypeEntry) types.next();

                                    if ((type != entry)
                                            && (type.getBaseType() == null)
                                            && sameJavaClass(entry.getName(),
                                                    type.getName())) {
                                        v.add(type);
                                    }
                                }
                            }

                            // If this is an anonymous type, it's name was resolved in
                            // the previous if block.  Don't reresolve it.
                            if (!anonTypes.contains(entry)) {
                                // In case that other entry in name collision among 
                                // PortTypeEntry, ServiceEntry and BindingEntry
                                
                                boolean needResolve = false;
                                
                                // check collision of TypeEntry with PortTypeEntry, ServiceEtnry and/or BindingEntry 
                                for (int j = 0; j < v.size(); j++) {
                                    SymTabEntry e = (SymTabEntry) v.elementAt(j);
                                    if ((e instanceof PortTypeEntry 
                                            || e instanceof ServiceEntry
                                            || e instanceof BindingEntry)) {
                                        needResolve = true;
                                        break;
                                    }
                                }
                                
                                if (!needResolve) {
                                    continue;
                                }                                                                
                                
                                // Appended Suffix for avoiding name collisions (JAX-RPC 1.1)
                                boolean isComplexTypeFault = Utils.isFaultComplex(entry);
                                mangleName(entry, isComplexTypeFault ? EXCEPTION_SUFFIX : TYPE_SUFFIX);
                                
                                // should update the class name of ElementEntry which references this type entry
                                Map elementIndex = symbolTable.getElementIndex();
                                List elements = new ArrayList(elementIndex.values());
                                for (int j = 0; j < elementIndex.size(); j++) {
                                    TypeEntry te = (TypeEntry) elements.get(j);
                                    TypeEntry ref = te.getRefType();
                                    if (ref != null && entry.getQName().equals(ref.getQName())) {
                                        te.setName(entry.getName());
                                    }
                                }           
                                
                                // Need to resolve a complex-type exception message.
                                if (isComplexTypeFault) {
                                    // SHOULD update the exception class name of a referencing message entry.
                                    List messageEntries = symbolTable.getMessageEntries();
                                    for (int j = 0; j < messageEntries.size(); j++) {
                                        MessageEntry messageEntry = (MessageEntry)messageEntries.get(j);
                                        if (Utils.isFaultComplex(messageEntry)) {
                                            QName exceptionDataType = (QName)messageEntry.getDynamicVar(EXCEPTION_DATA_TYPE);
                                            if (((TypeEntry)entry).getQName().equals(exceptionDataType)) {
                                                String className = (String)messageEntry.getDynamicVar(EXCEPTION_CLASS_NAME);
                                                messageEntry.setDynamicVar(EXCEPTION_CLASS_NAME, className + EXCEPTION_SUFFIX);
                                            }
                                        }
                                    }
                                }
                            }
                        } else if (entry instanceof PortTypeEntry) {
                            mangleName(entry, PORT_TYPE_SUFFIX);   // "_Port" --> "_PortType" for JAX-RPC 1.1
                        } else if (entry instanceof ServiceEntry) {
                            mangleName(entry, SERVICE_SUFFIX);
                        } else if (entry instanceof MessageEntry) {
                            if (!Utils.isFaultComplex(entry)) {
                                String exceptionClassName = (String) entry.getDynamicVar(EXCEPTION_CLASS_NAME);
                                entry.setDynamicVar(EXCEPTION_CLASS_NAME, exceptionClassName + EXCEPTION_SUFFIX);
                            }                            
                        }
                        // else if (entry instanceof MessageEntry) {
                        // we don't care about messages
                        // }
                        else if (entry instanceof BindingEntry) {
                            BindingEntry bEntry = (BindingEntry) entry;

                            // If there is no literal use, then we never see a
                            // class named directly from the binding name.  They
                            // all have suffixes:  Stub, Skeleton, Impl.
                            // If there IS literal use, then the SDI will be
                            // named after the binding name, so there is the
                            // possibility of a name clash.
                            if (bEntry.hasLiteral()) {
                                mangleName(entry, BINDING_SUFFIX);
                            }
                        }
                    }
                }
            }
        }
    }                                          // resolveNameClashes