/*
* Copyright (C) 2013 Sebastian Sdorra
*
* 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 sonia.legman.maven;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
//~--- JDK imports ------------------------------------------------------------
import java.lang.annotation.Annotation;
import java.util.Set;
/**
*
* @author Sebastian Sdorra
*/
public class MethodAnnotationClassVisitor extends ClassVisitor
{
/**
* Constructs ...
*
*
* @param api
* @param methodAnnotationHandler
* @param annotationClasses
*/
private MethodAnnotationClassVisitor(int api,
MethodAnnotationHandler methodAnnotationHandler,
Iterable<Class<? extends Annotation>> annotationClasses)
{
super(api);
this.methodAnnotationHandler = methodAnnotationHandler;
ImmutableSet.Builder<String> builder = ImmutableSet.builder();
for (Class<? extends Annotation> annotationClass : annotationClasses)
{
builder.add(annotationClass.getName());
}
annotations = builder.build();
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @return
*/
public static Builder builder()
{
return new Builder();
}
/**
* Method description
*
*
* @param version
* @param access
* @param name
* @param signature
* @param superName
* @param interfaces
*/
@Override
public void visit(int version, int access, String name, String signature,
String superName, String[] interfaces)
{
this.className = transformDescToClassName(name);
super.visit(version, access, name, signature, superName, interfaces);
}
/**
* Method description
*
*
* @param access
* @param methodName
* @param desc
* @param signature
* @param exceptions
*
* @return
*/
@Override
public MethodVisitor visitMethod(int access, final String methodName,
String desc, String signature, String[] exceptions)
{
return new MethodVisitor(api)
{
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible)
{
String annotation = transformDescToClassName(desc);
if (annotations.contains(annotation))
{
methodAnnotationHandler.handleMethodAnnotation(className, methodName,
annotation);
}
return super.visitAnnotation(desc, visible);
}
};
}
/**
* Method description
*
*
* @param desc
*
* @return
*/
private String transformDescToClassName(String desc)
{
if (desc.startsWith("L") && desc.endsWith(";"))
{
desc = desc.substring(1).substring(0, desc.length() - 2);
}
return desc.replace('/', '.');
}
//~--- inner classes --------------------------------------------------------
/**
* Class description
*
*
* @version Enter version here..., 14/01/11
* @author Enter your name here...
*/
public static class Builder
{
/**
* Method description
*
*
* @param annotationClass
* @param annotationClasses
*
* @return
*/
public Builder annotateClasses(Class<? extends Annotation> annotationClass,
Class<? extends Annotation>... annotationClasses)
{
this.annotationClasses.addAll(Lists.asList(annotationClass,
annotationClasses));
return this;
}
/**
* Method description
*
*
* @param api
*
* @return
*/
public Builder api(int api)
{
this.api = api;
return this;
}
/**
* Method description
*
*
* @return
*/
public MethodAnnotationClassVisitor build()
{
return new MethodAnnotationClassVisitor(api, methodAnnotationHandler,
annotationClasses);
}
/**
* Method description
*
*
* @param methodAnnotationHandler
*
* @return
*/
public Builder methodAnnotationHandler(
MethodAnnotationHandler methodAnnotationHandler)
{
this.methodAnnotationHandler = methodAnnotationHandler;
return this;
}
//~--- fields -------------------------------------------------------------
/** Field description */
private int api = Opcodes.ASM4;
/** Field description */
private final Set<Class<? extends Annotation>> annotationClasses =
Sets.newHashSet();
/** Field description */
private MethodAnnotationHandler methodAnnotationHandler;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private final Set<String> annotations;
/** Field description */
private final MethodAnnotationHandler methodAnnotationHandler;
/** Field description */
private String className;
}