/**
* 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.modules.jaxb.model;
import com.webcohesion.enunciate.javac.decorations.element.DecoratedElement;
import com.webcohesion.enunciate.javac.decorations.element.DecoratedExecutableElement;
import com.webcohesion.enunciate.javac.decorations.element.DecoratedVariableElement;
import com.webcohesion.enunciate.javac.decorations.element.PropertyElement;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
import java.util.List;
/**
* Filter for potential accessors.
*
* @author Ryan Heaton
*/
public class AccessorFilter {
private final XmlAccessType accessType;
public AccessorFilter(XmlAccessType accessType) {
this.accessType = accessType;
if (accessType == null) {
throw new IllegalArgumentException("An access type must be specified.");
}
}
/**
* Whether to accept the given member declaration as an accessor.
*
* @param element The declaration to filter.
* @return Whether to accept the given member declaration as an accessor.
*/
public boolean accept(DecoratedElement<?> element) {
if (element.getAnnotation(XmlTransient.class) != null) {
return false;
}
if (element instanceof PropertyElement) {
PropertyElement property = ((PropertyElement) element);
if ("".equals(property.getPropertyName())) {
return false;
}
for (String annotationName : property.getAnnotations().keySet()) {
if (annotationName.startsWith("javax.xml.bind.annotation")) {
//if the property has an explicit annotation, we'll include it.
return true;
}
}
DecoratedExecutableElement getter = property.getGetter();
if (getter == null) {
//needs a getter.
return false;
}
DecoratedExecutableElement setter = property.getSetter();
if (setter == null) {
//needs a setter.
return false;
}
if (!getter.isPublic()) {
//we only have to worry about public methods ("properties" are only defined by public accessor methods).
return false;
}
if (!setter.isPublic()) {
//we only have to worry about public methods ("properties" are only defined by public accessor methods).
return false;
}
return (((accessType != XmlAccessType.NONE) && (accessType != XmlAccessType.FIELD)) || (explicitlyDeclaredAccessor(element)));
}
else if (element instanceof DecoratedVariableElement) {
if (element.isStatic() || element.isTransient()) {
return false;
}
if ((accessType == XmlAccessType.NONE) || (accessType == XmlAccessType.PROPERTY)) {
return explicitlyDeclaredAccessor(element);
}
if (accessType == XmlAccessType.PUBLIC_MEMBER) {
return (element.isPublic() || (explicitlyDeclaredAccessor(element)));
}
//the accessType is FIELD. Include it.
return true;
}
return false;
}
/**
* Whether the specified member declaration is explicitly declared to be an accessor.
*
* @param element The declaration to check whether it is explicitly declared to be an accessor.
* @return Whether the specified member declaration is explicitly declared to be an accessor.
*/
protected boolean explicitlyDeclaredAccessor(DecoratedElement<?> element) {
List<? extends AnnotationMirror> mirrors = element.getAnnotationMirrors();
for (AnnotationMirror annotationMirror : mirrors) {
DeclaredType annotationType = annotationMirror.getAnnotationType();
if (annotationType != null) {
TypeElement annotationDeclaration = (TypeElement) annotationType.asElement();
if ((annotationDeclaration != null) && (annotationDeclaration.getQualifiedName().toString().startsWith(XmlElement.class.getPackage().getName()))) {
//if it's annotated with anything in javax.xml.bind.annotation, (exception XmlTransient) we'll consider it to be "explicitly annotated."
return !annotationDeclaration.getQualifiedName().toString().equals(XmlTransient.class.getName());
}
}
}
return false;
}
}