/**
* 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.javac.decorations.element;
import com.webcohesion.enunciate.javac.decorations.DecoratedProcessingEnvironment;
import com.webcohesion.enunciate.javac.decorations.ElementDecorator;
import com.webcohesion.enunciate.javac.decorations.TypeMirrorDecorator;
import com.webcohesion.enunciate.javac.decorations.type.DecoratedReferenceType;
import com.webcohesion.enunciate.javac.decorations.type.DecoratedTypeMirror;
import com.webcohesion.enunciate.javac.javadoc.ParamDocComment;
import com.webcohesion.enunciate.javac.javadoc.ReturnDocComment;
import com.webcohesion.enunciate.javac.javadoc.ThrowsDocComment;
import javax.lang.model.element.*;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import java.beans.Introspector;
import java.util.List;
/**
* @author Ryan Heaton
*/
@SuppressWarnings ( "unchecked" )
public class DecoratedExecutableElement extends DecoratedElement<ExecutableElement> implements ExecutableElement {
private List<? extends VariableElement> parameters;
private List<? extends TypeMirror> thrownTypes;
private List<? extends TypeParameterElement> typeParameters;
private TypeMirror typeMirror;
public DecoratedExecutableElement(ExecutableElement delegate, DecoratedProcessingEnvironment env) {
super(delegate, env);
}
protected DecoratedExecutableElement(DecoratedExecutableElement copy) {
super(copy.delegate, copy.env);
this.parameters = copy.parameters;
this.thrownTypes = copy.thrownTypes;
this.typeParameters = copy.typeParameters;
this.typeMirror = copy.typeMirror;
}
private List<? extends TypeMirror> loadDecoratedThrownTypes(ExecutableElement delegate) {
List<? extends TypeMirror> thrownTypes = TypeMirrorDecorator.decorate(delegate.getThrownTypes(), env);
if (thrownTypes != null && !thrownTypes.isEmpty()) {
for (TypeMirror thrownType : thrownTypes) {
((DecoratedReferenceType)thrownType).setDocComment(new ThrowsDocComment(this, String.valueOf(thrownType)));
}
}
return thrownTypes;
}
private List<? extends VariableElement> loadDecoratedParameters() {
List<? extends VariableElement> parameters = ElementDecorator.decorate(((ExecutableElement) this.delegate).getParameters(), this.env);
if (parameters != null) {
for (VariableElement param : parameters) {
((DecoratedVariableElement) param).setDocComment(createParamDocComment(param));
}
}
return parameters;
}
protected ParamDocComment createParamDocComment(VariableElement param) {
return new ParamDocComment(this, param.getSimpleName().toString());
}
@Override
public List<? extends TypeParameterElement> getTypeParameters() {
if (this.typeParameters == null) {
this.typeParameters = ElementDecorator.decorate(delegate.getTypeParameters(), env);
}
return this.typeParameters;
}
@Override
public TypeMirror getReturnType() {
if (this.typeMirror == null) {
this.typeMirror = TypeMirrorDecorator.decorate(delegate.getReturnType(), env);
((DecoratedTypeMirror)this.typeMirror).setDocComment(new ReturnDocComment(this));
}
return this.typeMirror;
}
@Override
public boolean isVarArgs() {
return this.delegate.isVarArgs();
}
@Override
public AnnotationValue getDefaultValue() {
return this.delegate.getDefaultValue();
}
public List<? extends VariableElement> getParameters() {
if (this.parameters == null) {
this.parameters = loadDecoratedParameters();
}
return this.parameters;
}
public List<? extends TypeMirror> getThrownTypes() {
if (this.thrownTypes == null) {
this.thrownTypes = loadDecoratedThrownTypes(delegate);
}
return this.thrownTypes;
}
public boolean isGetter() {
return ((getSimpleName().toString().startsWith("get") || isIs()) && getParameters().isEmpty());
}
private boolean isIs() {
return getSimpleName().toString().startsWith("is") && (getReturnType().getKind() == TypeKind.BOOLEAN || ((DecoratedTypeMirror)getReturnType()).isInstanceOf(Boolean.class));
}
public boolean isSetter() {
return (getSimpleName().toString().startsWith("set") && getParameters().size() == 1);
}
public String getPropertyName() {
String propertyName = null;
if (isIs()) {
propertyName = Introspector.decapitalize(getSimpleName().toString().substring(2));
}
else if (isGetter() || (isSetter())) {
propertyName = Introspector.decapitalize(getSimpleName().toString().substring(3));
}
return propertyName;
}
@Override
public <R, P> R accept(ElementVisitor<R, P> v, P p) {
return v.visitExecutable(this, p);
}
}