/*
* Copyright 2012-2013 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Eclipse Public License version 1.0, available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.jboss.forge.roaster.model.ast;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.IExtendedModifier;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.jboss.forge.roaster.model.Annotation;
import org.jboss.forge.roaster.model.impl.AnnotationImpl;
import org.jboss.forge.roaster.model.source.AnnotationSource;
import org.jboss.forge.roaster.model.source.AnnotationTargetSource;
import org.jboss.forge.roaster.model.source.JavaSource;
import org.jboss.forge.roaster.model.util.Types;
/**
* @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
*/
public class AnnotationAccessor<O extends JavaSource<O>, T>
{
public AnnotationSource<O> addAnnotation(final AnnotationTargetSource<O, T> target, final ASTNode body)
{
return addAnnotation(target, getModifiers(body));
}
public AnnotationSource<O> addAnnotation(final AnnotationTargetSource<O, T> target,
final SingleVariableDeclaration variableDeclaration)
{
return addAnnotation(target, variableDeclaration.modifiers());
}
private AnnotationSource<O> addAnnotation(final AnnotationTargetSource<O, T> target, final List<?> modifiers)
{
@SuppressWarnings("unchecked")
ListIterator<IExtendedModifier> iter = (ListIterator<IExtendedModifier>) modifiers.listIterator();
while (iter.hasNext() && iter.next().isAnnotation())
;
// the effect of this is to back up only if the last encountered modifier is _not_ an annotation:
if (iter.hasPrevious() && iter.previous().isAnnotation())
{
iter.next();
}
AnnotationSource<O> annotation = new AnnotationImpl<O, T>(target);
iter.add((IExtendedModifier) annotation.getInternal());
return annotation;
}
public AnnotationSource<O> addAnnotation(final AnnotationTargetSource<O, T> target, final ASTNode body,
final Class<?> clazz)
{
return addAnnotation(target, getModifiers(body), clazz.getName());
}
public AnnotationSource<O> addAnnotation(final AnnotationTargetSource<O, T> target,
final SingleVariableDeclaration variableDeclaration,
final Class<?> clazz)
{
return addAnnotation(target, variableDeclaration.modifiers(), clazz.getName());
}
public AnnotationSource<O> addAnnotation(final AnnotationTargetSource<O, T> target, final ASTNode body,
final String className)
{
return addAnnotation(target, getModifiers(body), className);
}
public AnnotationSource<O> addAnnotation(final AnnotationTargetSource<O, T> target,
final SingleVariableDeclaration variableDeclaration,
final String className)
{
return addAnnotation(target, variableDeclaration.modifiers(), className);
}
private AnnotationSource<O> addAnnotation(final AnnotationTargetSource<O, T> target, final List<?> modifiers,
final String className)
{
if (target.getOrigin().requiresImport(className) && !target.getOrigin().hasImport(className)
&& Types.isQualified(className))
{
target.getOrigin().addImport(className);
}
return addAnnotation(target, modifiers).setName(Types.toSimpleName(className));
}
public List<AnnotationSource<O>> getAnnotations(final AnnotationTargetSource<O, T> target, final ASTNode body)
{
return getAnnotations(target, getModifiers(body));
}
public List<AnnotationSource<O>> getAnnotations(final AnnotationTargetSource<O, T> target,
final SingleVariableDeclaration variableDeclaration)
{
return getAnnotations(target, variableDeclaration.modifiers());
}
private List<AnnotationSource<O>> getAnnotations(final AnnotationTargetSource<O, T> target, final List<?> modifiers)
{
List<AnnotationSource<O>> result = new ArrayList<AnnotationSource<O>>();
for (Object object : modifiers)
{
if (object instanceof org.eclipse.jdt.core.dom.Annotation)
{
AnnotationSource<O> annotation = new AnnotationImpl<O, T>(target, object);
result.add(annotation);
}
}
return Collections.unmodifiableList(result);
}
public <E extends AnnotationTargetSource<O, T>> E removeAnnotation(final E target, final ASTNode body,
final Annotation<O> annotation)
{
return removeAnnotation(target, getModifiers(body), annotation);
}
public <E extends AnnotationTargetSource<O, T>> E removeAnnotation(final E target,
final SingleVariableDeclaration variableDeclaration,
final Annotation<O> annotation)
{
return removeAnnotation(target, variableDeclaration.modifiers(), annotation);
}
private <E extends AnnotationTargetSource<O, T>> E removeAnnotation(final E target, final List<?> modifiers,
final Annotation<O> annotation)
{
for (Object object : modifiers)
{
if (object.equals(annotation.getInternal()))
{
modifiers.remove(object);
break;
}
}
return target;
}
public void removeAllAnnotations(final ASTNode body)
{
removeAllAnnotations(getModifiers(body));
}
public void removeAllAnnotations(final SingleVariableDeclaration variableDeclaration)
{
removeAllAnnotations(variableDeclaration.modifiers());
}
private static void removeAllAnnotations(final List<?> modifiers)
{
Iterator<?> iterator = modifiers.iterator();
while (iterator.hasNext())
{
Object object = iterator.next();
if (object instanceof org.eclipse.jdt.core.dom.Annotation)
{
iterator.remove();
}
}
}
public <E extends AnnotationTargetSource<O, T>> boolean hasAnnotation(final E target, final ASTNode body,
final String type)
{
return hasAnnotation(target, getModifiers(body), type);
}
public <E extends AnnotationTargetSource<O, T>> boolean hasAnnotation(final E target,
final SingleVariableDeclaration variableDeclaration,
final String type)
{
return hasAnnotation(target, variableDeclaration.modifiers(), type);
}
private <E extends AnnotationTargetSource<O, T>> boolean hasAnnotation(final E target, final List<?> modifiers,
final String type)
{
for (Object object : modifiers)
{
if (object instanceof org.eclipse.jdt.core.dom.Annotation)
{
AnnotationSource<O> annotation = new AnnotationImpl<O, T>(target, object);
String annotationType = annotation.getName();
if (Types.areEquivalent(type, annotationType))
{
return true;
}
}
}
return false;
}
public AnnotationSource<O> getAnnotation(final AnnotationTargetSource<O, T> target, final ASTNode body,
final Class<? extends java.lang.annotation.Annotation> type)
{
return getAnnotation(target, getModifiers(body), type.getName());
}
public AnnotationSource<O> getAnnotation(final AnnotationTargetSource<O, T> target,
final SingleVariableDeclaration variableDeclaration,
final Class<? extends java.lang.annotation.Annotation> type)
{
return getAnnotation(target, variableDeclaration.modifiers(), type.getName());
}
public AnnotationSource<O> getAnnotation(final AnnotationTargetSource<O, T> target, final ASTNode body,
final String type)
{
return getAnnotation(target, getModifiers(body), type);
}
public AnnotationSource<O> getAnnotation(final AnnotationTargetSource<O, T> target,
final SingleVariableDeclaration variableDeclaration, final String type)
{
return getAnnotation(target, variableDeclaration.modifiers(), type);
}
private AnnotationSource<O> getAnnotation(final AnnotationTargetSource<O, T> target, final List<?> modifiers,
final String type)
{
List<AnnotationSource<O>> annotations = getAnnotations(target, modifiers);
for (AnnotationSource<O> annotation : annotations)
{
if (Types.areEquivalent(type, annotation.getName()))
{
return annotation;
}
}
return null;
}
private static List<?> getModifiers(final ASTNode body)
{
if (body instanceof BodyDeclaration)
{
return ((BodyDeclaration) body).modifiers();
}
else if (body instanceof PackageDeclaration)
{
return ((PackageDeclaration) body).annotations();
}
return Collections.emptyList();
}
}