/* Copyright (C) 2009 Versant Inc. http://www.db4o.com */
package sharpen.core;
import org.eclipse.jdt.core.dom.*;
import static sharpen.core.framework.Environments.*;
public class CRefBuilder {
private ASTNode _crefTarget;
public CRefBuilder(ASTNode ref) {
_crefTarget = ref;
}
public String build() {
switch (_crefTarget.getNodeType()) {
case ASTNode.SIMPLE_NAME:
case ASTNode.QUALIFIED_NAME:
return mapCRefTarget(_crefTarget, ((Name) _crefTarget).resolveBinding());
case ASTNode.MEMBER_REF:
return mapCRefTarget(_crefTarget, ((MemberRef) _crefTarget).resolveBinding());
case ASTNode.METHOD_REF:
return mapCRefTarget(_crefTarget, ((MethodRef) _crefTarget).resolveBinding());
}
return null;
}
private String mapCRefTarget(ASTNode node, IBinding binding) {
if (null == binding) {
my(Configuration.class).getWarningHandler().warning(node, "Unresolved cref target");
return node.toString();
}
return documentationNameFor(binding);
}
private String documentationNameFor(IBinding binding) {
switch (binding.getKind()) {
case IBinding.METHOD:
return methodSignatureForDocumentation((IMethodBinding) binding);
case IBinding.TYPE:
return mappedTypeName((ITypeBinding) binding);
case IBinding.VARIABLE:
return mappedQualifiedFieldName((IVariableBinding) binding);
case IBinding.PACKAGE:
return mappedNamespace(((IPackageBinding) binding).getName());
}
throw new IllegalArgumentException("Binding type not supported: " + binding);
}
private String methodSignatureForDocumentation(final IMethodBinding method) {
StringBuilder methodFQN = new StringBuilder();
if (belongsToCurrentType(method)) {
methodFQN.append(mappedMethodName(method));
} else {
methodFQN.append(mappedQualifiedMethodName(method));
}
final String parameterList = parameterListSeparatedBy(method, ", ");
methodFQN.append(genericTypeParametersFor(method));
methodFQN.append("(");
methodFQN.append(parameterList);
methodFQN.append(")");
return methodFQN.toString();
}
private boolean belongsToCurrentType(IMethodBinding method) {
return _currentType == method.getDeclaringClass();
}
private String mappedQualifiedMethodName(IMethodBinding binding) {
String methodName = mappedMethodName(binding);
if (methodName.indexOf('.') > -1) {
return methodName;
}
return mappedTypeName(binding.getDeclaringClass()) + "." + methodName;
}
private String genericTypeParametersFor(IMethodBinding method) {
final IMethodBinding bind = method.getMethodDeclaration();
return genericQualifierFor(bind.getTypeParameters());
}
private String genericQualifierFor(final ITypeBinding[] typeParameters) {
if (typeParameters.length == 0)
return "";
return "{" + typesSeparatedBy(typeParameters, ", ") + "}";
}
private String parameterListSeparatedBy(final IMethodBinding binding, final String separator) {
return typesSeparatedBy(binding.getParameterTypes(), separator);
}
private String typesSeparatedBy(final ITypeBinding[] types, final String separator) {
StringBuilder result = new StringBuilder();
for (ITypeBinding parameter : types) {
if (result.length() > 0) {
result.append(separator);
}
result.append(mappedTypeName(parameter));
}
return result.toString();
}
private String mappedMethodName(IMethodBinding binding) {
return my(Mappings.class).mappedMethodName(binding);
}
private String mappedQualifiedFieldName(IVariableBinding binding) {
String name = my(Mappings.class).mappedFieldName(binding);
if (null != name)
return name;
final String fieldName = identifier(binding.getName());
if (_currentType == binding.getDeclaringClass())
return fieldName;
return mappedTypeName(binding.getDeclaringClass()) + "." + fieldName;
}
private String mappedTypeName(ITypeBinding type) {
if (type.isArray()){
int dimensions = type.getDimensions();
StringBuilder sb = new StringBuilder();
for(int i =0; i < dimensions; i++){
sb.append("[]");
}
return mappedTypeName(type.getElementType()) + sb;
}
final String mappedTypeName = my(Mappings.class).mappedTypeName(type);
final String effectiveTypeName = _currentType.getPackage() == type.getPackage()
? simpleName(mappedTypeName)
: mappedTypeName;
return effectiveTypeName + genericQualifierFor(type.getTypeDeclaration().getTypeParameters());
}
private String simpleName(String typeName) {
final int lastDot = typeName.lastIndexOf('.');
return lastDot > 0
? typeName.substring(lastDot + 1)
: typeName;
}
private String identifier(String name) {
return my(Configuration.class).getNamingStrategy().identifier(name);
}
private String mappedNamespace(String namespace) {
return my(Configuration.class).mappedNamespace(namespace);
}
private final ITypeBinding _currentType = my(NameScope.class).currentType().resolveBinding();
}