/**
* Copyright © 2006-2016 Web Cohesion (info@webcohesion.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.webcohesion.enunciate.util.freemarker;
import com.webcohesion.enunciate.EnunciateContext;
import com.webcohesion.enunciate.util.HasClientConvertibleType;
import freemarker.template.TemplateModelException;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.type.*;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* Used to output a reference for an accessor or parameter or declaration.
*
* @author Ryan Heaton
*/
public class ClientClassnameForMethod extends ClientPackageForMethod {
protected final LinkedList<String> typeParameterDeclarationStack = new LinkedList<String>();
public ClientClassnameForMethod(Map<String, String> conversions, EnunciateContext context) {
super(conversions, context);
}
@Override
public String convertUnwrappedObject(Object unwrapped) throws TemplateModelException {
if (unwrapped instanceof HasClientConvertibleType) {
return convert((HasClientConvertibleType) unwrapped);
}
else if (unwrapped instanceof TypeParameterElement) {
return convert((TypeParameterElement) unwrapped);
}
else {
return super.convertUnwrappedObject(unwrapped);
}
}
/**
* Converts the specified type parameter declaration.
*
* @param typeParameterElement The type parameter declaration.
* @return The type parameter declaration.
*/
public String convert(TypeParameterElement typeParameterElement) throws TemplateModelException {
String conversion = typeParameterElement.getSimpleName().toString();
if (typeParameterElement.getBounds() != null && !typeParameterElement.getBounds().isEmpty() && !typeParameterDeclarationStack.contains(conversion)) {
typeParameterDeclarationStack.addFirst(conversion);
try {
conversion += " extends " + convert(typeParameterElement.getBounds().iterator().next());
}
finally {
typeParameterDeclarationStack.removeFirst();
}
}
return conversion;
}
public String convert(HasClientConvertibleType element) throws TemplateModelException {
return convert(element.getClientConvertibleType());
}
@Override
public String convert(TypeMirror typeMirror) throws TemplateModelException {
String conversion;
if (typeMirror instanceof WildcardType) {
conversion = convert((WildcardType) typeMirror);
}
else if (typeMirror instanceof TypeVariable) {
return convert((TypeVariable) typeMirror);
}
else {
conversion = super.convert(typeMirror);
boolean isArray = typeMirror.getKind() == TypeKind.ARRAY;
if (typeMirror instanceof DeclaredType) {
conversion += convertDeclaredTypeArguments(((DeclaredType) typeMirror).getTypeArguments());
}
if (isArray) {
conversion += "[]";
}
}
return conversion;
}
public String convert(WildcardType wildCard) throws TemplateModelException {
String conversion;
if (wildCard.getSuperBound() != null) {
conversion = "? super " + convert(wildCard.getSuperBound());
}
else if (wildCard.getExtendsBound() != null) {
conversion = "? extends " + convert(wildCard.getExtendsBound());
}
else {
conversion = "?";
}
return conversion;
}
public String convertDeclaredTypeArguments(List<? extends TypeMirror> actualTypeArguments) throws TemplateModelException {
StringBuilder typeArgs = new StringBuilder();
if (actualTypeArguments.size() > 0) {
typeArgs.append("<");
Iterator<? extends TypeMirror> it = actualTypeArguments.iterator();
while (it.hasNext()) {
TypeMirror mirror = it.next();
typeArgs.append(convert(mirror));
if (it.hasNext()) {
typeArgs.append(", ");
}
}
typeArgs.append(">");
}
return typeArgs.toString();
}
public String convert(TypeVariable variableMirror) throws TemplateModelException {
TypeParameterElement parameterElement = (TypeParameterElement) variableMirror.asElement();
return parameterElement.getSimpleName().toString();
}
@Override
public String convert(TypeElement declaration) throws TemplateModelException {
PackageElement pkg = this.context.getProcessingEnvironment().getElementUtils().getPackageOf(declaration);
String convertedPackage = convertPackage(pkg);
String simpleName = declaration.getSimpleName().toString();
return convertedPackage + getPackageSeparator() + simpleName;
}
protected String convertPackage(PackageElement pkg) {
return super.convert(pkg);
}
protected String getPackageSeparator() {
return ".";
}
@Override
public String convert(PackageElement packageDeclaration) {
throw new UnsupportedOperationException("packages don't have a classname.");
}
}