/******************************************************************************* | |
* Copyright (c) 2009 by SAP AG, Walldorf. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v10.html | |
* | |
* Contributors: | |
* SAP AG - initial API and implementation | |
*******************************************************************************/ | |
package org.eclipse.jst.ws.jaxws.utils.annotations; | |
import java.io.FileNotFoundException; | |
import java.util.List; | |
import java.util.Set; | |
import org.eclipse.core.resources.IFile; | |
import org.eclipse.core.runtime.CoreException; | |
import org.eclipse.core.runtime.IStatus; | |
import org.eclipse.jdt.core.ICompilationUnit; | |
import org.eclipse.jdt.core.IField; | |
import org.eclipse.jdt.core.IJavaElement; | |
import org.eclipse.jdt.core.IMember; | |
import org.eclipse.jdt.core.IMethod; | |
import org.eclipse.jdt.core.IType; | |
import org.eclipse.jdt.core.ITypeParameter; | |
import org.eclipse.jdt.core.dom.AST; | |
import org.eclipse.jdt.core.dom.ASTNode; | |
import org.eclipse.jdt.core.dom.Annotation; | |
import org.eclipse.jdt.core.dom.BodyDeclaration; | |
import org.eclipse.jdt.core.dom.CompilationUnit; | |
import org.eclipse.jdt.core.dom.Expression; | |
import org.eclipse.jdt.core.dom.FieldDeclaration; | |
import org.eclipse.jdt.core.dom.IExtendedModifier; | |
import org.eclipse.jdt.core.dom.MethodDeclaration; | |
import org.eclipse.jdt.core.dom.SingleVariableDeclaration; | |
import org.eclipse.jdt.core.dom.TypeDeclaration; | |
import org.eclipse.jface.text.BadLocationException; | |
import org.eclipse.jface.text.IDocument; | |
import org.eclipse.jst.ws.jaxws.utils.clazz.ASTUtils; | |
import org.eclipse.jst.ws.jaxws.utils.internal.annotations.impl.AnnotationImpl; | |
import org.eclipse.jst.ws.jaxws.utils.internal.annotations.impl.AnnotationUtils; | |
import org.eclipse.jst.ws.jaxws.utils.internal.text.JaxWsUtilMessages; | |
import org.eclipse.jst.ws.jaxws.utils.resources.EditResourcesManager; | |
import org.eclipse.jst.ws.jaxws.utils.resources.FileUtils; | |
import org.eclipse.jst.ws.jaxws.utils.resources.IFileUtils; | |
import org.eclipse.text.edits.MalformedTreeException; | |
import org.eclipse.text.edits.TextEdit; | |
/** | |
* Class, which is used to save the annotations. | |
* | |
* @author Plamen Pavlov | |
* | |
*/ | |
public class AnnotationWriter | |
{ | |
private static AnnotationWriter writer = null; | |
private final IFileUtils fileUtils = FileUtils.getInstance(); | |
/** | |
* The factory method. | |
* | |
* @return a AnnotationWriter instance. | |
*/ | |
public static<T extends IJavaElement> AnnotationWriter getInstance() | |
{ | |
if (writer == null) | |
{ | |
writer = new AnnotationWriter(); | |
} | |
return writer; | |
} | |
/** | |
* Adds Annotation to specific IJavaElement. | |
* | |
* @param javaElement | |
* | |
* @throws NullPointerException if <tt>javaElement</tt> is null. | |
* @throws IllegalArgumentException in case <code>javaElement</code> is not of the correct type. Supported types are: IType, IMethod, IField, ITypeParameter. | |
* @throws AnnotationGeneratorException. | |
*/ | |
public <T extends IJavaElement> void setAppliedElement(final IAnnotation<T> annotation, final T javaElement) throws AnnotationGeneratorException | |
{ | |
AnnotationImpl<T> annotationImpl = (AnnotationImpl<T>)annotation; | |
annotationImpl.setJavaElement(javaElement); | |
setAnnotatationStringVallue(annotationImpl, true, javaElement); | |
} | |
private <T extends IJavaElement> void setAnnotatationStringVallue(AnnotationImpl<T> annotationImpl, boolean needSave, final T javaElement) throws AnnotationGeneratorException | |
{ | |
if (!needSave) { | |
return; | |
} | |
if(javaElement instanceof IType) | |
{ | |
addToClass(annotationImpl, (IType)javaElement); | |
} | |
if(javaElement instanceof IField) | |
{ | |
addToField(annotationImpl, (IField)javaElement); | |
} | |
if(javaElement instanceof IMethod) | |
{ | |
addToMethod(annotationImpl, (IMethod)javaElement); | |
} | |
if(javaElement instanceof ITypeParameter) | |
{ | |
addToParam(annotationImpl, (ITypeParameter)javaElement); | |
} | |
} | |
private <T extends IJavaElement> void addToClass(AnnotationImpl<T> annotationImpl, IType classType) throws AnnotationGeneratorException | |
{ | |
String className = classType.getElementName(); | |
addToMember(annotationImpl, classType.getCompilationUnit(), classType, className); | |
} | |
private <T extends IJavaElement> void addToField(AnnotationImpl<T> annotationImpl, IField fieldType) throws AnnotationGeneratorException | |
{ | |
String className = fieldType.getParent().getElementName(); | |
addToMember(annotationImpl, fieldType.getCompilationUnit(), fieldType, className); | |
} | |
private <T extends IJavaElement> void addToMethod(AnnotationImpl<T> annotationImpl, IMethod methodType) throws AnnotationGeneratorException | |
{ | |
String className = methodType.getParent().getElementName(); | |
addToMember(annotationImpl, methodType.getCompilationUnit(), methodType, className); | |
} | |
private <T extends IJavaElement> void addToParam(AnnotationImpl<T> annotationImpl, ITypeParameter typeParam) throws AnnotationGeneratorException | |
{ | |
IMember member = typeParam.getDeclaringMember(); | |
String className = null; | |
if (member.getElementType() == IJavaElement.METHOD) | |
{ | |
className = member.getDeclaringType().getElementName(); | |
} else | |
{ | |
className = member.getElementName(); | |
} | |
addToMember(annotationImpl, member.getCompilationUnit(), typeParam, className); | |
} | |
private <T extends IJavaElement> void addToMember(AnnotationImpl<T> annotationImpl, ICompilationUnit cUnit, IJavaElement type, String className) throws AnnotationGeneratorException | |
{ | |
try | |
{ | |
if (cUnit == null) | |
{ | |
return; | |
} | |
CompilationUnit unit = ASTUtils.getInstance().createCompilationUnit(cUnit, null); | |
AST ast = unit.getAST(); | |
TypeDeclaration typeDeclaration = (TypeDeclaration)ASTUtils.getInstance().getTypeDeclaration(className, unit); | |
if (typeDeclaration != null) | |
{ | |
switch (type.getElementType()) | |
{ | |
case IJavaElement.TYPE: | |
addAnnotation(annotationImpl, cUnit, unit, ast, typeDeclaration); | |
break; | |
case IJavaElement.METHOD: | |
MethodDeclaration methodDeclaration = ASTUtils.getInstance().getMethodDeclaration((IMethod) type, typeDeclaration); | |
addAnnotation(annotationImpl, cUnit, unit, ast, methodDeclaration); | |
break; | |
case IJavaElement.FIELD: | |
FieldDeclaration fieldDeclaration = ASTUtils.getInstance().getFieldDeclaration((IField) type, typeDeclaration); | |
addAnnotation(annotationImpl, cUnit, unit, ast, fieldDeclaration); | |
break; | |
case IJavaElement.TYPE_PARAMETER: | |
ITypeParameter typeParameter = (ITypeParameter) type; | |
if (typeParameter.getDeclaringMember().getElementType() == IJavaElement.METHOD) | |
{ | |
methodDeclaration = ASTUtils.getInstance().getMethodDeclaration((IMethod) typeParameter.getDeclaringMember(), typeDeclaration); | |
SingleVariableDeclaration paramDeclaration = getParamDeclaration(typeParameter, methodDeclaration); | |
addAnnotation(annotationImpl, cUnit, unit, ast, paramDeclaration); | |
} | |
break; | |
default: | |
throw new IllegalArgumentException("unsupported type for annotation"); //$NON-NLS-1$ | |
} | |
} | |
} | |
catch (MalformedTreeException e) | |
{ | |
throw new AnnotationGeneratorException(e.getMessage(), JaxWsUtilMessages.InvalidTreeStateMsg, e); | |
} | |
catch (CoreException e) | |
{ | |
throw new AnnotationGeneratorException(e.getMessage(), e.getStatus().getMessage(), e); | |
} | |
catch (BadLocationException e) | |
{ | |
throw new AnnotationGeneratorException(e.getMessage(), JaxWsUtilMessages.CannotPerformEditMsg, e); | |
} | |
catch (FileNotFoundException e) | |
{ | |
throw new AnnotationGeneratorException(e.getMessage(), JaxWsUtilMessages.CompUnitMissingMsg, e); | |
} | |
} | |
@SuppressWarnings("unchecked") | |
private <T extends IJavaElement> void addAnnotation(AnnotationImpl<T> annotationImpl, ICompilationUnit cUnit, CompilationUnit unit, AST ast, ASTNode declaration) | |
throws CoreException, MalformedTreeException, BadLocationException, FileNotFoundException, AnnotationGeneratorException | |
{ | |
editResManager().setFileEditable((IFile) cUnit.getResource()); | |
unit.recordModifications(); | |
Expression annot = annotationImpl.getExpression(unit, ast); | |
List modifiers = null; | |
switch (declaration.getNodeType()) | |
{ | |
case ASTNode.METHOD_DECLARATION: | |
case ASTNode.FIELD_DECLARATION: | |
case ASTNode.TYPE_DECLARATION: | |
modifiers = ((BodyDeclaration) declaration).modifiers(); | |
break; | |
case ASTNode.SINGLE_VARIABLE_DECLARATION: | |
modifiers = ((SingleVariableDeclaration) declaration).modifiers(); | |
break; | |
default: | |
throw new IllegalArgumentException("addAnnotation() illegal declataion type"); //$NON-NLS-1$ | |
} | |
modifiers.add(0, annot); | |
IDocument doc = AnnotationUtils.getInstance().getDocument(cUnit); | |
TextEdit edit = unit.rewrite(doc, null); | |
edit.apply(doc); | |
IStatus status = editResManager().setFileEditable((IFile) cUnit.getResource()); | |
if(status.getSeverity() == IStatus.OK) | |
{ | |
fileUtils.setCompilationUnitContentAndSaveDirtyEditors(cUnit, doc.get(), true, null); | |
} | |
else | |
{ | |
throw new AnnotationGeneratorException("Annotattion could not be stored, the file is not writable", //$NON-NLS-1$ | |
JaxWsUtilMessages.AnnotationCannotBeStoredMsg); | |
} | |
} | |
private static SingleVariableDeclaration getParamDeclaration(ITypeParameter typeParameter, MethodDeclaration methodDeclaration) | |
{ | |
//TODO check this method | |
final String paramName = typeParameter.getElementName(); | |
for (Object decl : methodDeclaration.parameters()) | |
{ | |
if (!(decl instanceof SingleVariableDeclaration)) | |
{ | |
continue; | |
} | |
if (paramName.equals(((SingleVariableDeclaration) decl).getName().toString())) | |
{ | |
return (SingleVariableDeclaration) decl; | |
} | |
} | |
return null; | |
} | |
/** | |
* Updates the Parameter-Value Pairs of specific Annotation. | |
* | |
* @param annotation - Annotation, which will be updated. | |
* @throws AnnotationGeneratorException | |
* @throws CoreException | |
*/ | |
public <T extends IJavaElement> void update(final IAnnotation<T> annotation) throws AnnotationGeneratorException, CoreException | |
{ | |
AnnotationImpl<T> annotattionImpl = new AnnotationImpl<T>(annotation.getAnnotationName(), annotation.getParamValuePairs()); | |
try | |
{ | |
updateTheAnnotation(annotation.getAppliedElement(), annotattionImpl); | |
} | |
catch(MalformedTreeException e) { | |
throw new AnnotationGeneratorException(e.getMessage(), JaxWsUtilMessages.InvalidTreeStateMsg, e); | |
} | |
catch (BadLocationException e) { | |
throw new AnnotationGeneratorException(e.getMessage(), JaxWsUtilMessages.CannotPerformEditMsg, e); | |
} | |
catch (FileNotFoundException e) { | |
throw new AnnotationGeneratorException(e.getMessage(), JaxWsUtilMessages.CompUnitMissingMsg, e); | |
} | |
} | |
/** | |
* Updates the Param-Value Pairs of specific Annotation. | |
* | |
* @param annotation - Annotation, which will be updated. | |
* @param paramValuePairs which will be updated. Old pairs will be replaced with the new once. | |
* @param replacePreviousPairs boolean value which specifies the way, how new IParamValuePairs will be updated. If the value is <tt>true</tt>, | |
* the Set with the old IParamValuePairs will be cleared and the new values will be applied. If the value is <tt>false</tt> the old pairs will be kept | |
* and will be updated with the values from the new Set, if there are params which do not exist in the old one, they will be added. | |
* | |
* @throws CoreException | |
* @throws AnnotationGeneratorException | |
* | |
* @deprecated - use public <T extends IJavaElement> void update(final IAnnotation<T> annotation) instead. | |
*/ | |
@Deprecated | |
public <T extends IJavaElement> void update(final IAnnotation<T> annotation, Set<IParamValuePair> paramValuePairs, boolean replacePreviousPairs) throws AnnotationGeneratorException, CoreException | |
{ | |
updateAnnotation(annotation, annotation.getAppliedElement(), paramValuePairs, replacePreviousPairs); | |
} | |
/** | |
* | |
* @param <T> | |
* @param annotation | |
* @param javaElement | |
* @param paramValuePairs | |
* @param replacePreviousPairs | |
* @throws AnnotationGeneratorException | |
* @throws CoreException | |
* | |
*/ | |
private <T extends IJavaElement> void updateAnnotation(final IAnnotation<T> annotation, final T javaElement, Set<IParamValuePair> paramValuePairs, boolean replacePreviousPairs) throws AnnotationGeneratorException, CoreException | |
{ | |
AnnotationImpl<T> annotationImpl = (AnnotationImpl<T>)annotation; | |
try | |
{ | |
if(replacePreviousPairs) | |
{ | |
annotationImpl.setParamValuePairs(paramValuePairs); | |
} | |
else | |
{ | |
for (IParamValuePair pair : paramValuePairs) | |
{ | |
boolean isUpdated = false; | |
Set<IParamValuePair> tmpParamValuePairs = annotationImpl.getParamValuePairs(); | |
for (IParamValuePair thisPair : tmpParamValuePairs) | |
{ | |
if(thisPair.getParam().equals(pair.getParam())) | |
{ | |
tmpParamValuePairs.remove(thisPair); | |
tmpParamValuePairs.add(pair); | |
isUpdated = true; | |
break; | |
} | |
} | |
if(!isUpdated) | |
{ | |
tmpParamValuePairs.add(pair); | |
} | |
annotationImpl.setParamValuePairs(tmpParamValuePairs); | |
} | |
} | |
updateTheAnnotation(javaElement, annotationImpl); | |
//remove(annotation); | |
//setAppliedElement(annotation, javaElement); | |
} | |
catch(MalformedTreeException e) { | |
throw new AnnotationGeneratorException(e.getMessage(), JaxWsUtilMessages.InvalidTreeStateMsg, e); | |
} | |
catch (BadLocationException e) { | |
throw new AnnotationGeneratorException(e.getMessage(), JaxWsUtilMessages.CannotPerformEditMsg, e); | |
} | |
catch (FileNotFoundException e) { | |
throw new AnnotationGeneratorException(e.getMessage(), JaxWsUtilMessages.CompUnitMissingMsg, e); | |
} | |
} | |
/** | |
* Removes Annotation. | |
* | |
* @param annotation - Annotation, which will be removed. | |
* | |
* @throws BadLocationException | |
* @throws CoreException | |
* @throws AnnotationGeneratorException | |
* @throws FileNotFoundException | |
*/ | |
public <T extends IJavaElement> void remove(final IAnnotation<T> annotation) throws AnnotationGeneratorException, CoreException | |
{ | |
removeAnnotation(annotation, annotation.getAppliedElement()); | |
} | |
private <T extends IJavaElement> void removeAnnotation(final IAnnotation<T> annotation, final T javaElement) throws AnnotationGeneratorException, CoreException | |
{ | |
AnnotationImpl<T> annotationImpl = (AnnotationImpl<T>)annotation; | |
try | |
{ | |
// if(annotationImpl.getAnnotationStringValue() == null || annotationImpl.getAnnotationStringValue().trim().equals("")) | |
// { | |
// annotationImpl.setAnnotationStringValue(createAnnotatationStringVallue(annotationImpl, javaElement)); | |
// AnnotationUtils.getInstance().removeAnnotation(javaElement, annotationImpl.getAnnotationStringValue()); | |
// } | |
// else | |
// { | |
AnnotationUtils.getInstance().removeAnnotation(javaElement, annotationImpl.getSimpleAnnotationName()); | |
// } | |
} catch (BadLocationException ble) | |
{ | |
throw new AnnotationGeneratorException(ble.getMessage(), JaxWsUtilMessages.CannotPerformEditMsg, ble); | |
} catch (FileNotFoundException fnfe) | |
{ | |
throw new AnnotationGeneratorException(fnfe.getMessage(), JaxWsUtilMessages.CompUnitMissingMsg, fnfe); | |
} | |
} | |
// i036509 added | |
@SuppressWarnings("unchecked") | |
private <T extends IJavaElement> void updateTheAnnotation(final T javaElement, final AnnotationImpl<T> annotationImpl) throws BadLocationException, CoreException, AnnotationGeneratorException, FileNotFoundException | |
{ | |
final ICompilationUnit iCu = getCu(javaElement); | |
final CompilationUnit unit = ASTUtils.getInstance().createCompilationUnit(iCu, null); | |
BodyDeclaration bd = null; | |
Annotation found = null; | |
if(javaElement instanceof IType) | |
{ | |
bd = ASTUtils.getInstance().getTypeDeclaration(javaElement.getElementName(), unit); | |
found = findAnnotation(bd, annotationImpl); | |
unit.recordModifications(); | |
if (found!=null) { | |
bd.modifiers().remove(found); | |
} | |
final Expression annot = annotationImpl.getExpression(unit, unit.getAST()); | |
bd.modifiers().add(0, annot); | |
} | |
if(javaElement instanceof IMethod) | |
{ | |
TypeDeclaration td = (TypeDeclaration)ASTUtils.getInstance().getTypeDeclaration(((IMethod)javaElement).getDeclaringType().getElementName(), unit); | |
bd = ASTUtils.getInstance().getMethodDeclaration(((IMethod)javaElement), td); | |
found = findAnnotation(bd, annotationImpl); | |
unit.recordModifications(); | |
if (found!=null) { | |
bd.modifiers().remove(found); | |
} | |
final Expression annot = annotationImpl.getExpression(unit, unit.getAST()); | |
bd.modifiers().add(0, annot); | |
} | |
if(javaElement instanceof IField) | |
{ | |
TypeDeclaration td = (TypeDeclaration)ASTUtils.getInstance().getTypeDeclaration(((IField)javaElement).getDeclaringType().getElementName(), unit); | |
bd = ASTUtils.getInstance().getFieldDeclaration(((IField)javaElement), td); | |
found = findAnnotation(bd, annotationImpl); | |
unit.recordModifications(); | |
if (found!=null) { | |
bd.modifiers().remove(found); | |
} | |
final Expression annot = annotationImpl.getExpression(unit, unit.getAST()); | |
bd.modifiers().add(0, annot); | |
} | |
if(javaElement instanceof ITypeParameter) | |
{ | |
if(((ITypeParameter)javaElement).getDeclaringMember() instanceof IType) | |
{ | |
bd = ASTUtils.getInstance().getTypeDeclaration(((ITypeParameter)javaElement).getDeclaringMember().getElementName(), unit); | |
SingleVariableDeclaration param = findParameter(bd, javaElement); | |
if(param != null) | |
{ | |
found = findParamAnnotation(param, annotationImpl, javaElement); | |
} | |
unit.recordModifications(); | |
if (found!=null) { | |
param.modifiers().remove(found); | |
} | |
final Expression annot = annotationImpl.getExpression(unit, unit.getAST()); | |
param.modifiers().add(0, annot); | |
} | |
else | |
{ | |
TypeDeclaration td = (TypeDeclaration)ASTUtils.getInstance().getTypeDeclaration(((IMethod)((ITypeParameter)javaElement).getParent()).getDeclaringType(). getElementName(), unit); | |
bd = ASTUtils.getInstance().getMethodDeclaration(((IMethod)((ITypeParameter)javaElement).getParent()), td); | |
SingleVariableDeclaration param = findParameter(bd, javaElement); | |
if(param != null) | |
{ | |
found = findParamAnnotation(param, annotationImpl, javaElement); | |
} | |
unit.recordModifications(); | |
if (found!=null) { | |
param.modifiers().remove(found); | |
} | |
final Expression annot = annotationImpl.getExpression(unit, unit.getAST()); | |
param.modifiers().add(0, annot); | |
} | |
} | |
setAnnotatationStringVallue(annotationImpl, false, javaElement); | |
final IDocument doc = AnnotationUtils.getInstance().getDocument(iCu); | |
final TextEdit edit = unit.rewrite(doc, javaElement.getJavaProject().getOptions(true)); | |
edit.apply(doc); | |
IStatus status = editResManager().setFileEditable((IFile) iCu.getResource()); | |
if(status.getSeverity() == IStatus.OK) | |
{ | |
fileUtils.setCompilationUnitContentAndSaveDirtyEditors(iCu, doc.get(), true, null); | |
} | |
else | |
{ | |
throw new AnnotationGeneratorException("Annotattion could not be stored, the file is not writable", //$NON-NLS-1$ | |
JaxWsUtilMessages.AnnotationCannotBeStoredMsg); | |
} | |
} | |
@SuppressWarnings("unchecked") | |
private Annotation findAnnotation(final BodyDeclaration td, final IAnnotation<? extends IJavaElement> annotation) | |
{ | |
Annotation ann; | |
for (IExtendedModifier modifier : (List<IExtendedModifier>)td.modifiers()) | |
{ | |
if(!modifier.isAnnotation()) { | |
continue; | |
} | |
ann = (Annotation)modifier; | |
if (annotation.getAnnotationName().endsWith(ann.getTypeName().getFullyQualifiedName())) { | |
return ann; | |
} | |
} | |
return null; | |
} | |
private <T extends IJavaElement> SingleVariableDeclaration findParameter(final BodyDeclaration td, T javaElement) | |
{ | |
if (td != null) | |
{ | |
for (Object param : ((MethodDeclaration)td).parameters()) | |
{ | |
if (param instanceof SingleVariableDeclaration && | |
((ITypeParameter)javaElement).getElementName().toString().equals(((SingleVariableDeclaration)param).getName().toString())) | |
{ | |
return (SingleVariableDeclaration)param; | |
} | |
} | |
} | |
return null; | |
} | |
@SuppressWarnings("unchecked") | |
private <T extends IJavaElement> Annotation findParamAnnotation(final SingleVariableDeclaration param, final IAnnotation<? extends IJavaElement> annotation, T javaElement) | |
{ | |
Annotation ann; | |
for (IExtendedModifier modifier : (List<IExtendedModifier>)(param.modifiers())) | |
{ | |
if(!modifier.isAnnotation()) { | |
continue; | |
} | |
ann = (Annotation)modifier; | |
if (annotation.getAnnotationName().endsWith(ann.getTypeName().getFullyQualifiedName())) { | |
return ann; | |
} | |
} | |
return null; | |
} | |
private ICompilationUnit getCu(final IJavaElement javaElement) | |
{ | |
switch (javaElement.getElementType()) | |
{ | |
case IJavaElement.TYPE: | |
return ((IType) javaElement).getCompilationUnit(); | |
case IJavaElement.FIELD: | |
return ((IField) javaElement).getCompilationUnit(); | |
case IJavaElement.METHOD: | |
return ((IMethod) javaElement).getCompilationUnit(); | |
case IJavaElement.TYPE_PARAMETER: | |
return ((ITypeParameter) javaElement).getDeclaringMember().getCompilationUnit(); | |
} | |
return null; | |
} | |
private EditResourcesManager editResManager() | |
{ | |
return new EditResourcesManager(); | |
} | |
} |