implement jdt annotation interface

Change-Id: I8d530f09319585e001fe8e6a019df7de0360b864
diff --git a/org.eclipse.capra.handler.jdt.tests/.classpath b/org.eclipse.capra.handler.jdt.tests/.classpath
new file mode 100644
index 0000000..eca7bdb
--- /dev/null
+++ b/org.eclipse.capra.handler.jdt.tests/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+	<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.capra.handler.jdt.tests/.project b/org.eclipse.capra.handler.jdt.tests/.project
new file mode 100644
index 0000000..be03059
--- /dev/null
+++ b/org.eclipse.capra.handler.jdt.tests/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.eclipse.capra.handler.jdt.tests</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.ManifestBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.pde.SchemaBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.pde.PluginNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/org.eclipse.capra.handler.jdt.tests/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.capra.handler.jdt.tests/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0c68a61
--- /dev/null
+++ b/org.eclipse.capra.handler.jdt.tests/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/org.eclipse.capra.handler.jdt.tests/META-INF/MANIFEST.MF b/org.eclipse.capra.handler.jdt.tests/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..10cda9d
--- /dev/null
+++ b/org.eclipse.capra.handler.jdt.tests/META-INF/MANIFEST.MF
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: JDT Handler tests
+Bundle-SymbolicName: org.eclipse.capra.handler.jdt.tests
+Bundle-Version: 0.7.0.qualifier
+Fragment-Host: org.eclipse.capra.handler.jdt;bundle-version="0.7.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: org.junit,
+ org.eclipse.core.resources,
+ org.eclipse.jdt.launching,
+ org.eclipse.jdt.core,
+ org.eclipse.capra.generic.persistence,
+ org.eclipse.capra.generic.tracemodels
diff --git a/org.eclipse.capra.handler.jdt.tests/build.properties b/org.eclipse.capra.handler.jdt.tests/build.properties
new file mode 100644
index 0000000..8553473
--- /dev/null
+++ b/org.eclipse.capra.handler.jdt.tests/build.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2016 Chalmers | University of Gothenburg, rt-labs and others.
+# 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:
+#      Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation
+###############################################################################
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .
diff --git a/org.eclipse.capra.handler.jdt.tests/pom.xml b/org.eclipse.capra.handler.jdt.tests/pom.xml
new file mode 100644
index 0000000..2a11fd0
--- /dev/null
+++ b/org.eclipse.capra.handler.jdt.tests/pom.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+	Copyright (c) 2016 Chalmers | University of Gothenburg, rt-labs and others.
+	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:
+		Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+	<modelVersion>4.0.0</modelVersion>
+
+	<parent>
+		<relativePath>../pom.xml</relativePath>
+		<groupId>org.eclipse.capra</groupId>
+		<artifactId>parent</artifactId>
+		<version>0.7.0-SNAPSHOT</version>
+	</parent>
+
+	<artifactId>org.eclipse.capra.handler.jdt.tests</artifactId>
+	<packaging>eclipse-test-plugin</packaging>
+
+</project>
diff --git a/org.eclipse.capra.handler.jdt.tests/src/org/eclipse/capra/handler/jdt/JDTAnnotateTest.java b/org.eclipse.capra.handler.jdt.tests/src/org/eclipse/capra/handler/jdt/JDTAnnotateTest.java
new file mode 100644
index 0000000..3c24c19
--- /dev/null
+++ b/org.eclipse.capra.handler.jdt.tests/src/org/eclipse/capra/handler/jdt/JDTAnnotateTest.java
@@ -0,0 +1,152 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Chalmers | University of Gothenburg, rt-labs and others.
+ * 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:
+ *      Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+package org.eclipse.capra.handler.jdt;
+
+import static org.junit.Assert.*;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class JDTAnnotateTest {
+
+	private JavaElementHandler handler = new JavaElementHandler();
+	private EObject artifactModel = TestUtil.setupModel();
+	private IProject project;
+
+	@Before
+	public void createTestProject() throws CoreException {
+		project = TestUtil.createTestProject("jdt");
+	}
+
+	@After
+	public void deleteTestProject() throws CoreException {
+		TestUtil.deleteTestProject(project);
+	}
+
+	@Test
+	public void shouldAnnotateClass() throws Exception {
+		String source = "" +
+				"package jdt\n" +
+				"public class bar {\n" +
+				"};\n";
+
+		ICompilationUnit cu = TestUtil.createCompilationUnit(project, "bar.java", source);
+
+		// Annotate class bar
+		EObject wrapper = TestUtil.createWrapper(artifactModel, "=jdt/src<jdt{bar.java[bar", "bar");
+		handler.annotateArtifact(wrapper, "annotation");
+		String actual = cu.getSource();
+
+		String expected = "" +
+				"package jdt\n" +
+				"/**\n" +
+				" * @req annotation\n" +
+				" */\n" +
+				"public class bar {\n" +
+				"};\n";
+
+		assertEquals(actual, expected);
+	}
+
+	@Test
+	public void shouldAnnotateMethod() throws Exception {
+		String source = "" +
+				"package jdt\n" +
+				"public class bar {\n" +
+				"int foo() { return 0; }\n" +
+				"};\n";
+
+		ICompilationUnit cu = TestUtil.createCompilationUnit(project, "bar.java", source);
+
+		// Annotate method foo()
+		EObject wrapper = TestUtil.createWrapper(artifactModel, "=jdt/src<jdt{bar.java[bar~foo", "foo");
+		handler.annotateArtifact(wrapper, "annotation");
+		String actual = cu.getSource();
+
+		String expected = "" +
+				"package jdt\n" +
+				"public class bar {\n" +
+				"/**\n" +
+				" * @req annotation\n" +
+				" */\n" +
+				"int foo() { return 0; }\n" +
+				"};\n";
+
+		assertEquals(actual, expected);
+	}
+
+	@Test
+	public void shouldReplaceAnnotation() throws Exception {
+		String source = "" +
+				"package jdt\n" +
+				"public class bar {\n" +
+				"/**\n" +
+				" * @req annotation1\n" +
+				" */\n" +
+				"int foo() { return 0; }\n" +
+				"};\n";
+
+		ICompilationUnit cu = TestUtil.createCompilationUnit(project, "bar.java", source);
+
+		// Annotate method foo()
+		EObject wrapper = TestUtil.createWrapper(artifactModel, "=jdt/src<jdt{bar.java[bar~foo", "foo");
+		handler.annotateArtifact(wrapper, "annotation2");
+		String actual = cu.getSource();
+
+		String expected = "" +
+				"package jdt\n" +
+				"public class bar {\n" +
+				"/**\n" +
+				" * @req annotation2\n" +
+				" */\n" +
+				"int foo() { return 0; }\n" +
+				"};\n";
+
+		assertEquals(actual, expected);
+	}
+
+	@Test
+	public void shouldPreserveComments() throws Exception {
+		String source = "" +
+				"package jdt\n" +
+				"public class bar {\n" +
+				"/**\n" +
+				" * Comment\n" +
+				" */\n" +
+				"int foo() { return 0; }\n" +
+				"};\n";
+
+		ICompilationUnit cu = TestUtil.createCompilationUnit(project, "bar.java", source);
+
+		// Annotate method foo()
+		EObject wrapper = TestUtil.createWrapper(artifactModel, "=jdt/src<jdt{bar.java[bar~foo", "foo");
+		handler.annotateArtifact(wrapper, "annotation");
+		String actual = cu.getSource();
+
+		String expected = "" +
+				"package jdt\n" +
+				"public class bar {\n" +
+				"/**\n" +
+				" * Comment\n" +
+				" * @req annotation\n" +
+				" */\n" +
+				"int foo() { return 0; }\n" +
+				"};\n";
+
+		assertEquals(actual, expected);
+	}
+
+}
diff --git a/org.eclipse.capra.handler.jdt.tests/src/org/eclipse/capra/handler/jdt/TestUtil.java b/org.eclipse.capra.handler.jdt.tests/src/org/eclipse/capra/handler/jdt/TestUtil.java
new file mode 100644
index 0000000..89b65da
--- /dev/null
+++ b/org.eclipse.capra.handler.jdt.tests/src/org/eclipse/capra/handler/jdt/TestUtil.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Chalmers | University of Gothenburg, rt-labs and others.
+ * 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:
+ *      Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+package org.eclipse.capra.handler.jdt;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.capra.core.adapters.ArtifactMetaModelAdapter;
+import org.eclipse.capra.core.adapters.TracePersistenceAdapter;
+import org.eclipse.capra.core.helpers.ExtensionPointHelper;
+import org.eclipse.core.resources.IFolder;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IPackageFragment;
+import org.eclipse.jdt.core.IPackageFragmentRoot;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.launching.IVMInstall;
+import org.eclipse.jdt.launching.JavaRuntime;
+import org.eclipse.jdt.launching.LibraryLocation;
+import org.junit.Before;
+
+public class TestUtil {
+
+	private static final String SRC_FOLDER = "src";
+
+	public static IProject createTestProject(String name) throws CoreException {
+		// Create the test project
+		IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+		IProject project = root.getProject(name);
+		project.create(null);
+		project.open(null);
+
+		// Add Java nature
+		IProjectDescription description = project.getDescription();
+		description.setNatureIds(new String[] { JavaCore.NATURE_ID });
+		project.setDescription(description, null);
+
+		// Create Java project
+		IJavaProject javaProject = JavaCore.create(project);
+
+		// Add output folder
+		IFolder binFolder = project.getFolder("bin");
+		javaProject.setOutputLocation(binFolder.getFullPath(), null);
+
+		// Set classpath
+		List<IClasspathEntry> entries = new ArrayList<IClasspathEntry>();
+		IVMInstall vmInstall = JavaRuntime.getDefaultVMInstall();
+		LibraryLocation[] locations = JavaRuntime.getLibraryLocations(vmInstall);
+		for (LibraryLocation element : locations) {
+			entries.add(JavaCore.newLibraryEntry(element.getSystemLibraryPath(), null, null));
+		}
+		// add libs to project class path
+		javaProject.setRawClasspath(entries.toArray(new IClasspathEntry[entries.size()]), null);
+
+		// Create source folder
+		IFolder sourceFolder = project.getFolder(SRC_FOLDER);
+		sourceFolder.create(false, true, null);
+
+		// Add source folder to classpath entries
+		IPackageFragmentRoot srcRoot = javaProject.getPackageFragmentRoot(sourceFolder);
+		IClasspathEntry[] oldEntries = javaProject.getRawClasspath();
+		IClasspathEntry[] newEntries = new IClasspathEntry[oldEntries.length + 1];
+		System.arraycopy(oldEntries, 0, newEntries, 0, oldEntries.length);
+		newEntries[oldEntries.length] = JavaCore.newSourceEntry(srcRoot.getPath());
+		javaProject.setRawClasspath(newEntries, null);
+
+		// Create default package
+		javaProject.getPackageFragmentRoot(sourceFolder).createPackageFragment(name, false, null);
+		return project;
+	}
+
+	public static void deleteTestProject(IProject project) throws CoreException {
+		project.delete(true, null);
+	}
+
+	@Before
+	public static EObject setupModel() {
+		TracePersistenceAdapter persistenceAdapter = ExtensionPointHelper.getTracePersistenceAdapter().get();
+		ResourceSet resourceSet = new ResourceSetImpl();
+		EObject artifactModel = persistenceAdapter.getArtifactWrappers(resourceSet);
+		return artifactModel;
+	}
+
+	public static ICompilationUnit createCompilationUnit(IProject project, String name, String source)
+			throws JavaModelException {
+		IFolder sourceFolder = project.getFolder(SRC_FOLDER);
+		IJavaProject javaProject = JavaCore.create(project);
+		IPackageFragment pack = javaProject.getPackageFragmentRoot(sourceFolder).getPackageFragment(project.getName());
+		return pack.createCompilationUnit(name, source, false, null);
+	}
+
+	public static ICompilationUnit createCompilationUnit(IProject project, String name, StringBuffer source)
+			throws JavaModelException {
+		return createCompilationUnit(project, name, source.toString());
+	}
+
+	public static EObject createWrapper(EObject artifactModel, String uri, String name) {
+		ArtifactMetaModelAdapter adapter = ExtensionPointHelper.getArtifactWrapperMetaModelAdapter().get();
+		return adapter.createArtifact(artifactModel, "org.eclipse.capra.handler.jdt.JavaElementHandler", uri, name);
+	}
+
+}
diff --git a/org.eclipse.capra.handler.jdt/META-INF/MANIFEST.MF b/org.eclipse.capra.handler.jdt/META-INF/MANIFEST.MF
index cd37bd5..21dd030 100644
--- a/org.eclipse.capra.handler.jdt/META-INF/MANIFEST.MF
+++ b/org.eclipse.capra.handler.jdt/META-INF/MANIFEST.MF
@@ -4,7 +4,9 @@
 Bundle-SymbolicName: org.eclipse.capra.handler.jdt;singleton:=true
 Bundle-Version: 0.7.0.qualifier
 Require-Bundle: org.eclipse.jdt.core,
- org.eclipse.capra.core;bundle-version="0.7.0",
- org.eclipse.emf.ecore
+ org.eclipse.capra.core,
+ org.eclipse.emf.ecore,
+ org.eclipse.jface.text,
+ org.eclipse.core.runtime
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
 Export-Package: org.eclipse.capra.handler.jdt
diff --git a/org.eclipse.capra.handler.jdt/src/org/eclipse/capra/handler/jdt/Activator.java b/org.eclipse.capra.handler.jdt/src/org/eclipse/capra/handler/jdt/Activator.java
new file mode 100644
index 0000000..09a7d8e
--- /dev/null
+++ b/org.eclipse.capra.handler.jdt/src/org/eclipse/capra/handler/jdt/Activator.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Chalmers | University of Gothenburg, rt-labs and others.
+ * 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:
+ *    Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+package org.eclipse.capra.handler.jdt;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+public class Activator implements BundleActivator {
+
+	public static final String PLUGIN_ID = "org.eclipse.capra.handler.jdt";
+
+	@Override
+	public void start(BundleContext context) throws Exception {
+	}
+
+	@Override
+	public void stop(BundleContext context) throws Exception {
+	}
+
+}
diff --git a/org.eclipse.capra.handler.jdt/src/org/eclipse/capra/handler/jdt/JDTAnnotate.java b/org.eclipse.capra.handler.jdt/src/org/eclipse/capra/handler/jdt/JDTAnnotate.java
new file mode 100644
index 0000000..86ecdd7
--- /dev/null
+++ b/org.eclipse.capra.handler.jdt/src/org/eclipse/capra/handler/jdt/JDTAnnotate.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Chalmers | University of Gothenburg, rt-labs and others.
+ * 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:
+ *      Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation
+ *******************************************************************************/
+package org.eclipse.capra.handler.jdt;
+
+import java.util.List;
+
+import org.eclipse.capra.core.handlers.AnnotationException;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.ISourceRange;
+import org.eclipse.jdt.core.ISourceReference;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTParser;
+import org.eclipse.jdt.core.dom.ChildPropertyDescriptor;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.Javadoc;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.NodeFinder;
+import org.eclipse.jdt.core.dom.TagElement;
+import org.eclipse.jdt.core.dom.TextElement;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
+import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.text.edits.MalformedTreeException;
+import org.eclipse.text.edits.TextEdit;
+
+public class JDTAnnotate {
+
+	private static final String TAG_NAME = "@req";
+	private static final String ANNOTATION_FAILED = "Annotation failed";
+
+	@SuppressWarnings("unchecked")
+	public static void annotateArtifact(IJavaElement handle, String annotation) throws AnnotationException {
+		if (handle instanceof ISourceReference) {
+			try {
+				ISourceReference sourceReference = (ISourceReference) handle;
+				ISourceRange range = sourceReference.getSourceRange();
+				ICompilationUnit cu = getCompilationUnit(sourceReference);
+				ASTParser parser = ASTParser.newParser(AST.JLS8);
+
+				String source = cu.getSource();
+				IDocument document = new Document(source);
+				parser.setSource(cu);
+
+				CompilationUnit root = (CompilationUnit) parser.createAST(null);
+				ASTRewrite rewrite = ASTRewrite.create(root.getAST());
+				ASTNode node = getNode(root, range.getOffset(), range.getLength());
+				AST ast = node.getAST();
+
+				ChildPropertyDescriptor property = getJavadocPropertyDescriptor(handle);
+				Javadoc javaDoc = (Javadoc) rewrite.get(node, property);
+				if (javaDoc == null)
+					javaDoc = ast.newJavadoc();
+
+				ListRewrite tagsRewriter = rewrite.getListRewrite(javaDoc, Javadoc.TAGS_PROPERTY);
+
+				// TODO: Get tag name from somewhere else
+
+				// Remove existing tags
+				((List<TagElement>)javaDoc.tags())
+					.stream()
+					.filter(t -> t.getTagName() != null && t.getTagName().equals(TAG_NAME))
+					.forEach(t -> tagsRewriter.remove(t, null));
+
+				// Create new tag
+				TagElement tag = ast.newTagElement();
+				TextElement text = ast.newTextElement();
+				text.setText(annotation);
+				tag.fragments().add(text);
+				tag.setTagName(TAG_NAME);
+
+				tagsRewriter.insertLast(tag, null);
+
+				rewrite.set(node, property, javaDoc, null);
+				TextEdit edit = rewrite.rewriteAST();
+				edit.apply(document);
+
+				String newSource = document.get();
+				cu.getBuffer().setContents(newSource);
+			} catch (JavaModelException e) {
+				throw new AnnotationException(e.getStatus());
+			} catch (MalformedTreeException e) {
+				Status status = new Status(Status.INFO, Activator.PLUGIN_ID, ANNOTATION_FAILED, e.getCause());
+				throw new AnnotationException(status);
+			} catch (BadLocationException e) {
+				Status status = new Status(Status.INFO, Activator.PLUGIN_ID, ANNOTATION_FAILED, e.getCause());
+				throw new AnnotationException(status);
+			}
+		}
+	}
+
+	private static ASTNode getNode(ASTNode root, int offset, int length) {
+		NodeFinder finder = new NodeFinder(root, offset, length);
+		ASTNode result = finder.getCoveringNode();
+		if (result != null)
+			return result;
+		return finder.getCoveredNode();
+	}
+
+	private static ICompilationUnit getCompilationUnit(ISourceReference o) {
+		if (o instanceof ICompilationUnit)
+			return (ICompilationUnit) o;
+		if (o instanceof IMethod)
+			return ((IMethod) o).getCompilationUnit();
+		if (o instanceof IJavaElement)
+			return (ICompilationUnit) ((IJavaElement) o).getAncestor(IJavaElement.COMPILATION_UNIT);
+		return null;
+	}
+
+	private static ChildPropertyDescriptor getJavadocPropertyDescriptor(IJavaElement handle) {
+		switch (handle.getElementType()) {
+		case IJavaElement.METHOD:
+			return MethodDeclaration.JAVADOC_PROPERTY;
+		case IJavaElement.TYPE:
+			return TypeDeclaration.JAVADOC_PROPERTY;
+		default:
+			return MethodDeclaration.JAVADOC_PROPERTY;
+		}
+	}
+
+}
diff --git a/org.eclipse.capra.handler.jdt/src/org/eclipse/capra/handler/jdt/JavaElementHandler.java b/org.eclipse.capra.handler.jdt/src/org/eclipse/capra/handler/jdt/JavaElementHandler.java
index df804f1..86aacbb 100644
--- a/org.eclipse.capra.handler.jdt/src/org/eclipse/capra/handler/jdt/JavaElementHandler.java
+++ b/org.eclipse.capra.handler.jdt/src/org/eclipse/capra/handler/jdt/JavaElementHandler.java
@@ -4,14 +4,16 @@
  * 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:
  *      Chalmers | University of Gothenburg and rt-labs - initial API and implementation and/or initial documentation
  *******************************************************************************/
 package org.eclipse.capra.handler.jdt;
 
 import org.eclipse.capra.core.adapters.ArtifactMetaModelAdapter;
+import org.eclipse.capra.core.handlers.AnnotationException;
 import org.eclipse.capra.core.handlers.ArtifactHandler;
+import org.eclipse.capra.core.handlers.IAnnotateArtifact;
 import org.eclipse.capra.core.helpers.ExtensionPointHelper;
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.jdt.core.IJavaElement;
@@ -21,7 +23,7 @@
  * A handler to allow creating traces to and from java elements such as classes
  * and methods based on JDT.
  */
-public class JavaElementHandler implements ArtifactHandler {
+public class JavaElementHandler implements ArtifactHandler, IAnnotateArtifact {
 
 	@Override
 	public boolean canHandleSelection(Object selection) {
@@ -54,4 +56,9 @@
 		return cu.getElementName();
 	}
 
+	@Override
+	public void annotateArtifact(EObject artifact, String annotation) throws AnnotationException {
+		IJavaElement handle = resolveArtifact(artifact);
+		JDTAnnotate.annotateArtifact(handle, annotation);
+	}
 }