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