[198934] resolve Constant Expressions
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/IJpaContentNode.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/IJpaContentNode.java
index 5d83c12..5676d2e 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/IJpaContentNode.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/IJpaContentNode.java
@@ -1,8 +1,8 @@
 /*******************************************************************************
  * Copyright (c) 2006, 2007 Oracle. 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.
+ * 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:
  *     Oracle - initial API and implementation
@@ -35,12 +35,6 @@
 	Object getId();
 
 	/**
-	 * Return the text range for this contentNode.  This is the all-inclusive
-	 * text range to be used for finding a particular content node given a source location.
-	 */
-	ITextRange fullTextRange();
-
-	/**
 	 * Return the text range to be used for selection. This is the text you want selected
 	 * when selecting the object in the editor. StructureView uses this for selection
 	 * from the structure to the source editor.
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/JpaCompilationUnit.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/JpaCompilationUnit.java
index a65a6d3..f7e1964 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/JpaCompilationUnit.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/JpaCompilationUnit.java
@@ -13,6 +13,7 @@
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
+
 import org.eclipse.core.resources.IFile;
 import org.eclipse.emf.common.notify.NotificationChain;
 import org.eclipse.emf.common.util.EList;
@@ -34,7 +35,6 @@
 import org.eclipse.jpt.core.internal.ITextRange;
 import org.eclipse.jpt.core.internal.JpaCorePackage;
 import org.eclipse.jpt.core.internal.JpaFile;
-import org.eclipse.jpt.core.internal.jdtutility.ASTNodeTextRange;
 import org.eclipse.jpt.core.internal.jdtutility.AttributeAnnotationTools;
 import org.eclipse.jpt.core.internal.jdtutility.JDTTools;
 import org.eclipse.jpt.utility.internal.BitTools;
@@ -289,10 +289,6 @@
 		return super.eDerivedStructuralFeatureID(baseFeatureID, baseClass);
 	}
 
-	public ITextRange fullTextRange() {
-		return new ASTNodeTextRange(this.astRoot());
-	}
-
 	public ITextRange validationTextRange() {
 		return this.selectionTextRange();
 	}
@@ -446,8 +442,8 @@
 		return EmptyIterator.instance();
 	}
 
-	public CompilationUnit astRoot() {
-		return JDTTools.createASTRoot(this.compilationUnit);
+	private CompilationUnit astRoot() {
+		return JDTTools.buildASTRoot(this.compilationUnit);
 	}
 
 	public void dispose() {
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaBasic.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaBasic.java
index d939946..2bb982f 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaBasic.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaBasic.java
@@ -10,6 +10,7 @@
 package org.eclipse.jpt.core.internal.content.java.mappings;
 
 import java.util.Iterator;
+
 import org.eclipse.emf.common.notify.Notification;
 import org.eclipse.emf.common.notify.NotificationChain;
 import org.eclipse.emf.ecore.EClass;
@@ -21,7 +22,6 @@
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.WorkingCopyOwner;
-import org.eclipse.jdt.core.dom.BooleanLiteral;
 import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jpt.core.internal.IMappingKeys;
 import org.eclipse.jpt.core.internal.jdtutility.AnnotationAdapter;
@@ -752,7 +752,7 @@
 
 	// ********** static methods **********
 	private static DeclarationAnnotationElementAdapter<String> buildOptionalAdapter() {
-		return new ConversionDeclarationAnnotationElementAdapter<String, BooleanLiteral>(DECLARATION_ANNOTATION_ADAPTER, JPA.BASIC__OPTIONAL, false, BooleanStringExpressionConverter.instance());
+		return new ConversionDeclarationAnnotationElementAdapter<String>(DECLARATION_ANNOTATION_ADAPTER, JPA.BASIC__OPTIONAL, false, BooleanStringExpressionConverter.instance());
 	}
 
 	private static DeclarationAnnotationElementAdapter<String> buildFetchAdapter() {
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaEntity.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaEntity.java
index be1dcd9..af5eee8 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaEntity.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaEntity.java
@@ -12,6 +12,7 @@
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
+
 import org.eclipse.emf.common.notify.Notification;
 import org.eclipse.emf.common.notify.NotificationChain;
 import org.eclipse.emf.common.util.EList;
@@ -23,7 +24,6 @@
 import org.eclipse.emf.ecore.util.InternalEList;
 import org.eclipse.jdt.core.dom.Annotation;
 import org.eclipse.jdt.core.dom.CompilationUnit;
-import org.eclipse.jdt.core.dom.TypeLiteral;
 import org.eclipse.jpt.core.internal.IMappingKeys;
 import org.eclipse.jpt.core.internal.IPersistentAttribute;
 import org.eclipse.jpt.core.internal.IPersistentType;
@@ -3006,6 +3006,6 @@
 
 	// ********** static methods **********
 	private static DeclarationAnnotationElementAdapter<String> buildIdClassValueAdapter() {
-		return new ConversionDeclarationAnnotationElementAdapter<String, TypeLiteral>(ID_CLASS_ADAPTER, JPA.ID_CLASS__VALUE, false, SimpleTypeStringExpressionConverter.instance());
+		return new ConversionDeclarationAnnotationElementAdapter<String>(ID_CLASS_ADAPTER, JPA.ID_CLASS__VALUE, false, SimpleTypeStringExpressionConverter.instance());
 	}
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaGenerator.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaGenerator.java
index 8066e53..25c53ac 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaGenerator.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaGenerator.java
@@ -13,7 +13,6 @@
 import org.eclipse.emf.ecore.EClass;
 import org.eclipse.emf.ecore.impl.ENotificationImpl;
 import org.eclipse.jdt.core.dom.CompilationUnit;
-import org.eclipse.jdt.core.dom.NumberLiteral;
 import org.eclipse.jpt.core.internal.ITextRange;
 import org.eclipse.jpt.core.internal.content.java.JavaEObject;
 import org.eclipse.jpt.core.internal.jdtutility.AnnotationElementAdapter;
@@ -565,6 +564,6 @@
 	}
 
 	protected static DeclarationAnnotationElementAdapter<String> buildNumberAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName) {
-		return new ConversionDeclarationAnnotationElementAdapter<String, NumberLiteral>(annotationAdapter, elementName, NumberStringExpressionConverter.instance());
+		return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, elementName, NumberStringExpressionConverter.instance());
 	}
 } // JavaGenerator
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaMappedSuperclass.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaMappedSuperclass.java
index 90a5383..0b90431 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaMappedSuperclass.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaMappedSuperclass.java
@@ -10,11 +10,11 @@
 package org.eclipse.jpt.core.internal.content.java.mappings;
 
 import java.util.Iterator;
+
 import org.eclipse.emf.common.notify.Notification;
 import org.eclipse.emf.ecore.EClass;
 import org.eclipse.emf.ecore.impl.ENotificationImpl;
 import org.eclipse.jdt.core.dom.CompilationUnit;
-import org.eclipse.jdt.core.dom.TypeLiteral;
 import org.eclipse.jpt.core.internal.IMappingKeys;
 import org.eclipse.jpt.core.internal.IPersistentAttribute;
 import org.eclipse.jpt.core.internal.jdtutility.AnnotationAdapter;
@@ -337,6 +337,6 @@
 
 	// ********** static methods **********
 	private static DeclarationAnnotationElementAdapter<String> buildIdClassValueAdapter() {
-		return new ConversionDeclarationAnnotationElementAdapter<String, TypeLiteral>(ID_CLASS_ADAPTER, JPA.ID_CLASS__VALUE, false, SimpleTypeStringExpressionConverter.instance());
+		return new ConversionDeclarationAnnotationElementAdapter<String>(ID_CLASS_ADAPTER, JPA.ID_CLASS__VALUE, false, SimpleTypeStringExpressionConverter.instance());
 	}
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaNamedColumn.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaNamedColumn.java
index 61b7da6..abfb4c3 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaNamedColumn.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaNamedColumn.java
@@ -10,12 +10,11 @@
 package org.eclipse.jpt.core.internal.content.java.mappings;
 
 import java.util.Iterator;
+
 import org.eclipse.emf.common.notify.Notification;
 import org.eclipse.emf.ecore.EClass;
 import org.eclipse.emf.ecore.impl.ENotificationImpl;
-import org.eclipse.jdt.core.dom.BooleanLiteral;
 import org.eclipse.jdt.core.dom.CompilationUnit;
-import org.eclipse.jdt.core.dom.NumberLiteral;
 import org.eclipse.jpt.core.internal.ITextRange;
 import org.eclipse.jpt.core.internal.content.java.JavaEObject;
 import org.eclipse.jpt.core.internal.jdtutility.AnnotationElementAdapter;
@@ -152,11 +151,11 @@
 	}
 
 	protected DeclarationAnnotationElementAdapter<String> buildBooleanElementAdapter(String elementName) {
-		return new ConversionDeclarationAnnotationElementAdapter<String, BooleanLiteral>(this.daa, elementName, BooleanStringExpressionConverter.instance());
+		return new ConversionDeclarationAnnotationElementAdapter<String>(this.daa, elementName, BooleanStringExpressionConverter.instance());
 	}
 
 	protected DeclarationAnnotationElementAdapter<String> buildIntElementAdapter(String elementName) {
-		return new ConversionDeclarationAnnotationElementAdapter<String, NumberLiteral>(this.daa, elementName, NumberStringExpressionConverter.instance());
+		return new ConversionDeclarationAnnotationElementAdapter<String>(this.daa, elementName, NumberStringExpressionConverter.instance());
 	}
 
 	protected AnnotationElementAdapter<String> buildShortCircuitElementAdapter(DeclarationAnnotationElementAdapter<String> daea) {
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaRelationshipMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaRelationshipMapping.java
index 9deacff..1b16973 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaRelationshipMapping.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaRelationshipMapping.java
@@ -10,6 +10,7 @@
 package org.eclipse.jpt.core.internal.content.java.mappings;
 
 import java.util.Iterator;
+
 import org.eclipse.emf.common.notify.Notification;
 import org.eclipse.emf.common.notify.NotificationChain;
 import org.eclipse.emf.ecore.EClass;
@@ -18,7 +19,6 @@
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.Signature;
 import org.eclipse.jdt.core.dom.CompilationUnit;
-import org.eclipse.jdt.core.dom.Expression;
 import org.eclipse.jpt.core.internal.IPersistentType;
 import org.eclipse.jpt.core.internal.ITypeMapping;
 import org.eclipse.jpt.core.internal.jdtutility.AnnotationElementAdapter;
@@ -562,7 +562,7 @@
 		if (this.cascade != null) {
 			((JavaCascade) this.cascade).updateFromJava(astRoot);
 		}
-		else if (cascadeAdapter().expression(getAttribute().modifiedDeclaration()) != null) {
+		else if (cascadeAdapter().expression(getAttribute().modifiedDeclaration(astRoot)) != null) {
 			setCascade(createCascade());
 			((JavaCascade) this.cascade).updateFromJava(astRoot);
 		}
@@ -654,8 +654,8 @@
 		return buildAnnotationElementAdapter(annotationAdapter, elementName, StringExpressionConverter.instance());
 	}
 
-	protected static <T extends Expression> DeclarationAnnotationElementAdapter<String> buildAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName, ExpressionConverter<String, T> converter) {
-		return new ConversionDeclarationAnnotationElementAdapter<String, T>(annotationAdapter, elementName, false, converter);
+	protected static DeclarationAnnotationElementAdapter<String> buildAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName, ExpressionConverter<String> converter) {
+		return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, elementName, false, converter);
 	}
 
 	protected static DeclarationAnnotationElementAdapter<String> buildEnumAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName) {
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaSingleRelationshipMapping.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaSingleRelationshipMapping.java
index 3639e7d..aa0415b 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaSingleRelationshipMapping.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaSingleRelationshipMapping.java
@@ -1,8 +1,8 @@
 /*******************************************************************************
  * Copyright (c) 2006, 2007 Oracle. 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.
+ * 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:
  *     Oracle - initial API and implementation
@@ -12,6 +12,7 @@
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
+
 import org.eclipse.emf.common.notify.Notification;
 import org.eclipse.emf.common.notify.NotificationChain;
 import org.eclipse.emf.common.util.EList;
@@ -20,7 +21,6 @@
 import org.eclipse.emf.ecore.impl.ENotificationImpl;
 import org.eclipse.emf.ecore.util.EObjectContainmentEList;
 import org.eclipse.emf.ecore.util.InternalEList;
-import org.eclipse.jdt.core.dom.BooleanLiteral;
 import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jpt.core.internal.jdtutility.AnnotationElementAdapter;
 import org.eclipse.jpt.core.internal.jdtutility.Attribute;
@@ -681,6 +681,6 @@
 
 	// ********** static methods **********
 	protected static DeclarationAnnotationElementAdapter<String> buildOptionalAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName) {
-		return new ConversionDeclarationAnnotationElementAdapter<String, BooleanLiteral>(annotationAdapter, elementName, false, BooleanStringExpressionConverter.instance());
+		return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, elementName, false, BooleanStringExpressionConverter.instance());
 	}
 } // JavaSingleRelationshipMapping
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaUniqueConstraint.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaUniqueConstraint.java
index 84055b9..01706c4 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaUniqueConstraint.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/content/java/mappings/JavaUniqueConstraint.java
@@ -11,13 +11,13 @@
 
 import java.util.Collection;
 import java.util.Iterator;
+
 import org.eclipse.emf.common.notify.Notification;
 import org.eclipse.emf.common.util.EList;
 import org.eclipse.emf.ecore.EClass;
 import org.eclipse.emf.ecore.util.EDataTypeEList;
 import org.eclipse.jdt.core.dom.Annotation;
 import org.eclipse.jdt.core.dom.CompilationUnit;
-import org.eclipse.jdt.core.dom.Expression;
 import org.eclipse.jpt.core.internal.ITextRange;
 import org.eclipse.jpt.core.internal.content.java.JavaEObject;
 import org.eclipse.jpt.core.internal.jdtutility.AnnotationElementAdapter;
@@ -97,11 +97,11 @@
 	}
 
 	protected static DeclarationAnnotationElementAdapter<String[]> buildArrayAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName) {
-		return buildArrayAnnotationElementAdapter(annotationAdapter, elementName, AnnotationStringArrayExpressionConverter.forStringLiterals());
+		return buildArrayAnnotationElementAdapter(annotationAdapter, elementName, AnnotationStringArrayExpressionConverter.forStrings());
 	}
 
-	protected static DeclarationAnnotationElementAdapter<String[]> buildArrayAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName, ExpressionConverter<String[], Expression> converter) {
-		return new ConversionDeclarationAnnotationElementAdapter<String[], Expression>(annotationAdapter, elementName, false, converter);
+	protected static DeclarationAnnotationElementAdapter<String[]> buildArrayAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName, ExpressionConverter<String[]> converter) {
+		return new ConversionDeclarationAnnotationElementAdapter<String[]>(annotationAdapter, elementName, false, converter);
 	}
 
 	@Override
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/AbstractExpressionConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/AbstractExpressionConverter.java
index cd87259..11f4ad3 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/AbstractExpressionConverter.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/AbstractExpressionConverter.java
@@ -14,26 +14,35 @@
 import org.eclipse.jpt.utility.internal.StringTools;
 
 /**
- * Gather together just the tiniest bit of common behavior.
- * E is the expression type.
+ * Gather together the common implementation behavior.
  * T is the type of the object to be converted to and from an expression.
+ * 
+ * We're still figuring out Java Generics here.... The methods in this abstract
+ * class work fine with any subclass of Expression E; but a ClassCastException
+ * will occur as soon as we call any method implemented by a subclass
+ * (e.g. StringExpressionConverter) that expects a particular subclass of
+ * Expression (e.g. StringLiteral).
  */
-public abstract class AbstractExpressionConverter<T, E extends Expression>
-	implements ExpressionConverter<T, E>
+public abstract class AbstractExpressionConverter<T>
+	implements ExpressionConverter<T>
 {
 
 	protected AbstractExpressionConverter() {
 		super();
 	}
 
-	public E convert(T object, AST ast) {
-		return (object == null) ? this.convertNull(ast) : this.convert_(object, ast);
+
+	// ********** object -> expression **********
+
+	public Expression convert(T object, AST ast) {
+		return (object == null) ? this.convertNull(ast) : this.convertObject(object, ast);
 	}
 
 	/**
-	 * Return the expression for a null object.
+	 * Return the expression for a null object. By default, a null object will
+	 * be converted into a null expression.
 	 */
-	protected E convertNull(AST ast) {
+	protected Expression convertNull(AST ast) {
 		return null;
 	}
 
@@ -41,14 +50,18 @@
 	 * The specified object is not null.
 	 * @see #convert(T, AST)
 	 */
-	protected abstract E convert_(T object, AST ast);
+	protected abstract Expression convertObject(T object, AST ast);
 
-	public T convert(E expression) {
-		return (expression == null) ? this.convertNull() : this.convert_(expression);
+
+	// ********** expression -> object **********
+
+	public T convert(Expression expression) {
+		return (expression == null) ? this.convertNull() : this.convertExpression(expression);
 	}
 
 	/**
-	 * Return the object for a null expression.
+	 * Return the object for a null expression. By default, a null expression will
+	 * be converted into a null object.
 	 */
 	protected T convertNull() {
 		return null;
@@ -58,7 +71,7 @@
 	 * The specified expression is not null.
 	 * @see #convert(Expression)
 	 */
-	protected abstract T convert_(E expression);
+	protected abstract T convertExpression(Expression expression);
 
 	@Override
 	public String toString() {
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/AnnotationStringArrayExpressionConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/AnnotationStringArrayExpressionConverter.java
index ad49351..21557f6 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/AnnotationStringArrayExpressionConverter.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/AnnotationStringArrayExpressionConverter.java
@@ -13,8 +13,6 @@
 import org.eclipse.jdt.core.dom.ASTNode;
 import org.eclipse.jdt.core.dom.ArrayInitializer;
 import org.eclipse.jdt.core.dom.Expression;
-import org.eclipse.jdt.core.dom.Name;
-import org.eclipse.jdt.core.dom.StringLiteral;
 
 /**
  * Convert an array initializer or single expression to/from an array of
@@ -22,24 +20,24 @@
  * E is the type of the expressions to be found either standalone or
  * as elements in the array initializer.
  */
-public class AnnotationStringArrayExpressionConverter<E extends Expression>
-	extends AbstractExpressionConverter<String[], Expression>
+public class AnnotationStringArrayExpressionConverter
+	extends AbstractExpressionConverter<String[]>
 {
-	private final ExpressionConverter<String, E> elementConverter;
-	private final StringArrayExpressionConverter<E> arrayConverter;
+	private final ExpressionConverter<String> elementConverter;
+	private final StringArrayExpressionConverter arrayConverter;
 
 
 	/**
 	 * The default behavior is to remove the array initializer if it is empty.
 	 */
-	public AnnotationStringArrayExpressionConverter(ExpressionConverter<String, E> elementConverter) {
+	public AnnotationStringArrayExpressionConverter(ExpressionConverter<String> elementConverter) {
 		this(elementConverter, true);
 	}
 
-	public AnnotationStringArrayExpressionConverter(ExpressionConverter<String, E> elementConverter, boolean removeArrayInitializerWhenEmpty) {
+	public AnnotationStringArrayExpressionConverter(ExpressionConverter<String> elementConverter, boolean removeArrayInitializerWhenEmpty) {
 		super();
 		this.elementConverter = elementConverter;
-		this.arrayConverter = new StringArrayExpressionConverter<E>(elementConverter, removeArrayInitializerWhenEmpty);
+		this.arrayConverter = new StringArrayExpressionConverter(elementConverter, removeArrayInitializerWhenEmpty);
 	}
 
 	/**
@@ -47,11 +45,11 @@
 	 * without braces, instead of an array initializer
 	 */
 	@Override
-	protected Expression convert_(String[] strings, AST ast) {
+	protected Expression convertObject(String[] strings, AST ast) {
 		return (strings.length == 1) ?
 				this.elementConverter.convert(strings[0], ast)
 			:
-				this.arrayConverter.convert_(strings, ast);
+				this.arrayConverter.convertObject(strings, ast);
 	}
 
 	@Override
@@ -64,16 +62,11 @@
 	 * single-entry array
 	 */
 	@Override
-	protected String[] convert_(Expression expression) {
+	protected String[] convertExpression(Expression expression) {
 		return (expression.getNodeType() == ASTNode.ARRAY_INITIALIZER) ?
-				this.arrayConverter.convert_((ArrayInitializer) expression)
+				this.arrayConverter.convertArrayInitializer((ArrayInitializer) expression)
 			:
-				new String[] {this.elementConverter.convert(this.downcastExpression(expression))};
-	}
-
-	@SuppressWarnings("unchecked")
-	private E downcastExpression(Expression expression) {
-		return (E) expression;
+				new String[] {this.elementConverter.convert(expression)};
 	}
 
 
@@ -85,8 +78,8 @@
 	 * or
 	 *     @Foo(bar="text0")
 	 */
-	public static AnnotationStringArrayExpressionConverter<StringLiteral> forStringLiterals() {
-		return new AnnotationStringArrayExpressionConverter<StringLiteral>(StringExpressionConverter.instance());
+	public static AnnotationStringArrayExpressionConverter forStrings() {
+		return new AnnotationStringArrayExpressionConverter(StringExpressionConverter.instance());
 	}
 
 	/**
@@ -95,8 +88,8 @@
 	 * or
 	 *     @Foo(bar=BAZ)
 	 */
-	public static AnnotationStringArrayExpressionConverter<Name> forNames() {
-		return new AnnotationStringArrayExpressionConverter<Name>(NameStringExpressionConverter.instance());
+	public static AnnotationStringArrayExpressionConverter forNames() {
+		return new AnnotationStringArrayExpressionConverter(NameStringExpressionConverter.instance());
 	}
 
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/BooleanStringExpressionConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/BooleanStringExpressionConverter.java
index 0f5854e..f7bf5d6 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/BooleanStringExpressionConverter.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/BooleanStringExpressionConverter.java
@@ -10,22 +10,22 @@
 package org.eclipse.jpt.core.internal.jdtutility;
 
 import org.eclipse.jdt.core.dom.AST;
-import org.eclipse.jdt.core.dom.ASTNode;
 import org.eclipse.jdt.core.dom.BooleanLiteral;
+import org.eclipse.jdt.core.dom.Expression;
 
 /**
  * Convert a boolean literal to/from a string representation of a boolean
  * (e.g. "true").
  */
 public final class BooleanStringExpressionConverter
-	extends AbstractExpressionConverter<String, BooleanLiteral>
+	extends AbstractExpressionConverter<String>
 {
-	private static ExpressionConverter<String, BooleanLiteral> INSTANCE;
+	private static ExpressionConverter<String> INSTANCE;
 
 	/**
 	 * Return the singleton.
 	 */
-	public static ExpressionConverter<String, BooleanLiteral> instance() {
+	public static ExpressionConverter<String> instance() {
 		if (INSTANCE == null) {
 			INSTANCE = new BooleanStringExpressionConverter();
 		}
@@ -40,16 +40,14 @@
 	}
 
 	@Override
-	protected BooleanLiteral convert_(String string, AST ast) {
+	protected BooleanLiteral convertObject(String string, AST ast) {
 		return ast.newBooleanLiteral(Boolean.valueOf(string).booleanValue());
 	}
 
 	@Override
-	protected String convert_(BooleanLiteral booleanLiteral) {
-		return (booleanLiteral.getNodeType() == ASTNode.BOOLEAN_LITERAL) ?
-			Boolean.toString(booleanLiteral.booleanValue())
-		:
-			null;
+	protected String convertExpression(Expression expression) {
+		Object value = expression.resolveConstantExpressionValue();
+		return (value instanceof Boolean) ? ((Boolean) value).toString() : null;
 	}
 
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/CharacterStringExpressionConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/CharacterStringExpressionConverter.java
index 1fa055d..dfc2fdc 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/CharacterStringExpressionConverter.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/CharacterStringExpressionConverter.java
@@ -10,22 +10,22 @@
 package org.eclipse.jpt.core.internal.jdtutility;
 
 import org.eclipse.jdt.core.dom.AST;
-import org.eclipse.jdt.core.dom.ASTNode;
 import org.eclipse.jdt.core.dom.CharacterLiteral;
+import org.eclipse.jdt.core.dom.Expression;
 
 /**
  * Convert a character literal to/from a string representation of a character
  * (e.g. "A").
  */
 public final class CharacterStringExpressionConverter
-	extends AbstractExpressionConverter<String, CharacterLiteral>
+	extends AbstractExpressionConverter<String>
 {
-	private static ExpressionConverter<String, CharacterLiteral> INSTANCE;
+	private static ExpressionConverter<String> INSTANCE;
 
 	/**
 	 * Return the singleton.
 	 */
-	public static ExpressionConverter<String, CharacterLiteral> instance() {
+	public static ExpressionConverter<String> instance() {
 		if (INSTANCE == null) {
 			INSTANCE = new CharacterStringExpressionConverter();
 		}
@@ -40,18 +40,16 @@
 	}
 	
 	@Override
-	protected CharacterLiteral convert_(String string, AST ast) {
+	protected CharacterLiteral convertObject(String string, AST ast) {
 		CharacterLiteral characterLiteral = ast.newCharacterLiteral();
 		characterLiteral.setCharValue(string.charAt(0));
 		return characterLiteral;
 	}
 
 	@Override
-	protected String convert_(CharacterLiteral characterLiteral) {
-		return (characterLiteral.getNodeType() == ASTNode.CHARACTER_LITERAL) ?
-			Character.toString(characterLiteral.charValue())
-		:
-			null;
+	protected String convertExpression(Expression expression) {
+		Object value = expression.resolveConstantExpressionValue();
+		return (value instanceof Character) ? ((Character) value).toString() : null;
 	}
 
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/ConversionDeclarationAnnotationElementAdapter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/ConversionDeclarationAnnotationElementAdapter.java
index 088fa0c..f6cf010 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/ConversionDeclarationAnnotationElementAdapter.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/ConversionDeclarationAnnotationElementAdapter.java
@@ -11,78 +11,51 @@
 
 import org.eclipse.jdt.core.dom.ASTNode;
 import org.eclipse.jdt.core.dom.Expression;
-import org.eclipse.jdt.core.dom.StringLiteral;
 import org.eclipse.jpt.utility.internal.StringTools;
 
 /**
  * Wrap a declaration annotation element adapter that deals with AST
  * expressions, converting them to/from various other objects.
  * T is the type of the object to be passed to and returned by the adapter.
- * E is the type of the expression to be converted by the converter.
  */
-public class ConversionDeclarationAnnotationElementAdapter<T, E extends Expression>
+public class ConversionDeclarationAnnotationElementAdapter<T>
 	implements DeclarationAnnotationElementAdapter<T>
 {
 	/**
 	 * The wrapped adapter that returns and takes AST expressions.
 	 */
-	private final DeclarationAnnotationElementAdapter<E> adapter;
+	private final DeclarationAnnotationElementAdapter<Expression> adapter;
 
 	/**
 	 * The converter that converts AST expressions to other objects
 	 * (e.g. Strings).
 	 */
-	private final ExpressionConverter<T, E> converter;
+	private final ExpressionConverter<T> converter;
 
 
 	// ********** constructors **********
 
 	/**
 	 * The default element name is "value"; the default behavior is to
-	 * remove the annotation when the last element is removed;
-	 * the default expression converter expects string literals.
-	 */
-	public static ConversionDeclarationAnnotationElementAdapter<String, StringLiteral> forStrings(DeclarationAnnotationAdapter annotationAdapter) {
-		return new ConversionDeclarationAnnotationElementAdapter<String, StringLiteral>(annotationAdapter, StringExpressionConverter.instance());
-	}
-
-	/**
-	 * The default element name is "value"; the default behavior is to
 	 * remove the annotation when the last element is removed.
 	 */
-	public ConversionDeclarationAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, ExpressionConverter<T, E> converter) {
-		this(new ExpressionDeclarationAnnotationElementAdapter<E>(annotationAdapter), converter);
-	}
-
-	/**
-	 * The default behavior is to remove the annotation when the last
-	 * element is removed; the default expression converter expects
-	 * string literals.
-	 */
-	public static ConversionDeclarationAnnotationElementAdapter<String, StringLiteral> forStrings(DeclarationAnnotationAdapter annotationAdapter, String elementName) {
-		return new ConversionDeclarationAnnotationElementAdapter<String, StringLiteral>(annotationAdapter, elementName, StringExpressionConverter.instance());
+	public ConversionDeclarationAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, ExpressionConverter<T> converter) {
+		this(new ExpressionDeclarationAnnotationElementAdapter<Expression>(annotationAdapter), converter);
 	}
 
 	/**
 	 * The default behavior is to remove the annotation when the last
 	 * element is removed.
 	 */
-	public ConversionDeclarationAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName, ExpressionConverter<T, E> converter) {
-		this(new ExpressionDeclarationAnnotationElementAdapter<E>(annotationAdapter, elementName), converter);
+	public ConversionDeclarationAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName, ExpressionConverter<T> converter) {
+		this(new ExpressionDeclarationAnnotationElementAdapter<Expression>(annotationAdapter, elementName), converter);
 	}
 
-	/**
-	 * The default expression converter expects string literals.
-	 */
-	public static ConversionDeclarationAnnotationElementAdapter<String, StringLiteral> forStrings(DeclarationAnnotationAdapter annotationAdapter, String elementName, boolean removeAnnotationWhenEmpty) {
-		return new ConversionDeclarationAnnotationElementAdapter<String, StringLiteral>(annotationAdapter, elementName, removeAnnotationWhenEmpty, StringExpressionConverter.instance());
+	public ConversionDeclarationAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName, boolean removeAnnotationWhenEmpty, ExpressionConverter<T> converter) {
+		this(new ExpressionDeclarationAnnotationElementAdapter<Expression>(annotationAdapter, elementName, removeAnnotationWhenEmpty), converter);
 	}
 
-	public ConversionDeclarationAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName, boolean removeAnnotationWhenEmpty, ExpressionConverter<T, E> converter) {
-		this(new ExpressionDeclarationAnnotationElementAdapter<E>(annotationAdapter, elementName, removeAnnotationWhenEmpty), converter);
-	}
-
-	public ConversionDeclarationAnnotationElementAdapter(DeclarationAnnotationElementAdapter<E> adapter, ExpressionConverter<T, E> converter) {
+	public ConversionDeclarationAnnotationElementAdapter(DeclarationAnnotationElementAdapter<Expression> adapter, ExpressionConverter<T> converter) {
 		super();
 		this.adapter = adapter;
 		this.converter = converter;
@@ -112,4 +85,107 @@
 		return StringTools.buildToStringFor(this, this.adapter);
 	}
 
+
+	// ********** factory static methods **********
+
+	/**
+	 * The default element name is "value"; the default behavior is to
+	 * remove the annotation when the last element is removed;
+	 * the default expression converter expects string constant expressions.
+	 */
+	public static ConversionDeclarationAnnotationElementAdapter<String> forStrings(DeclarationAnnotationAdapter annotationAdapter) {
+		return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, StringExpressionConverter.instance());
+	}
+
+	/**
+	 * The default behavior is to remove the annotation when the last
+	 * element is removed; the default expression converter expects
+	 * string constant expressions.
+	 */
+	public static ConversionDeclarationAnnotationElementAdapter<String> forStrings(DeclarationAnnotationAdapter annotationAdapter, String elementName) {
+		return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, elementName, StringExpressionConverter.instance());
+	}
+
+	/**
+	 * The default expression converter expects string constant expressions.
+	 */
+	public static ConversionDeclarationAnnotationElementAdapter<String> forStrings(DeclarationAnnotationAdapter annotationAdapter, String elementName, boolean removeAnnotationWhenEmpty) {
+		return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, elementName, removeAnnotationWhenEmpty, StringExpressionConverter.instance());
+	}
+
+	/**
+	 * The default element name is "value"; the default behavior is to
+	 * remove the annotation when the last element is removed;
+	 * the default expression converter expects number constant expressions.
+	 */
+	public static ConversionDeclarationAnnotationElementAdapter<String> forNumbers(DeclarationAnnotationAdapter annotationAdapter) {
+		return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, NumberStringExpressionConverter.instance());
+	}
+
+	/**
+	 * The default behavior is to remove the annotation when the last
+	 * element is removed; the default expression converter expects
+	 * number constant expressions.
+	 */
+	public static ConversionDeclarationAnnotationElementAdapter<String> forNumbers(DeclarationAnnotationAdapter annotationAdapter, String elementName) {
+		return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, elementName, NumberStringExpressionConverter.instance());
+	}
+
+	/**
+	 * The default expression converter expects number constant expressions.
+	 */
+	public static ConversionDeclarationAnnotationElementAdapter<String> forNumbers(DeclarationAnnotationAdapter annotationAdapter, String elementName, boolean removeAnnotationWhenEmpty) {
+		return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, elementName, removeAnnotationWhenEmpty, NumberStringExpressionConverter.instance());
+	}
+
+	/**
+	 * The default element name is "value"; the default behavior is to
+	 * remove the annotation when the last element is removed;
+	 * the default expression converter expects boolean constant expressions.
+	 */
+	public static ConversionDeclarationAnnotationElementAdapter<String> forBooleans(DeclarationAnnotationAdapter annotationAdapter) {
+		return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, BooleanStringExpressionConverter.instance());
+	}
+
+	/**
+	 * The default behavior is to remove the annotation when the last
+	 * element is removed; the default expression converter expects
+	 * boolean constant expressions.
+	 */
+	public static ConversionDeclarationAnnotationElementAdapter<String> forBooleans(DeclarationAnnotationAdapter annotationAdapter, String elementName) {
+		return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, elementName, BooleanStringExpressionConverter.instance());
+	}
+
+	/**
+	 * The default expression converter expects boolean constant expressions.
+	 */
+	public static ConversionDeclarationAnnotationElementAdapter<String> forBooleans(DeclarationAnnotationAdapter annotationAdapter, String elementName, boolean removeAnnotationWhenEmpty) {
+		return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, elementName, removeAnnotationWhenEmpty, BooleanStringExpressionConverter.instance());
+	}
+
+	/**
+	 * The default element name is "value"; the default behavior is to
+	 * remove the annotation when the last element is removed;
+	 * the default expression converter expects character constant expressions.
+	 */
+	public static ConversionDeclarationAnnotationElementAdapter<String> forCharacters(DeclarationAnnotationAdapter annotationAdapter) {
+		return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, CharacterStringExpressionConverter.instance());
+	}
+
+	/**
+	 * The default behavior is to remove the annotation when the last
+	 * element is removed; the default expression converter expects
+	 * character constant expressions.
+	 */
+	public static ConversionDeclarationAnnotationElementAdapter<String> forCharacters(DeclarationAnnotationAdapter annotationAdapter, String elementName) {
+		return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, elementName, CharacterStringExpressionConverter.instance());
+	}
+
+	/**
+	 * The default expression converter expects character constant expressions.
+	 */
+	public static ConversionDeclarationAnnotationElementAdapter<String> forCharacters(DeclarationAnnotationAdapter annotationAdapter, String elementName, boolean removeAnnotationWhenEmpty) {
+		return new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, elementName, removeAnnotationWhenEmpty, CharacterStringExpressionConverter.instance());
+	}
+
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/EnumArrayDeclarationAnnotationElementAdapter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/EnumArrayDeclarationAnnotationElementAdapter.java
index de08d4a..6330885 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/EnumArrayDeclarationAnnotationElementAdapter.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/EnumArrayDeclarationAnnotationElementAdapter.java
@@ -14,7 +14,6 @@
 import org.eclipse.jdt.core.dom.ASTNode;
 import org.eclipse.jdt.core.dom.ArrayInitializer;
 import org.eclipse.jdt.core.dom.Expression;
-import org.eclipse.jdt.core.dom.Name;
 
 /**
  * Wrap a declaration annotation element adapter and simply
@@ -26,7 +25,7 @@
 	/**
 	 * The wrapped adapter that returns and takes name strings (enums).
 	 */
-	private final ConversionDeclarationAnnotationElementAdapter<String[], Expression> adapter;
+	private final ConversionDeclarationAnnotationElementAdapter<String[]> adapter;
 
 	private static final String[] EMPTY_STRING_ARRAY = new String[0];
 
@@ -57,14 +56,14 @@
 	}
 
 	public EnumArrayDeclarationAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName, boolean removeAnnotationWhenEmpty, boolean removeArrayInitializerWhenEmpty) {
-		this(new ConversionDeclarationAnnotationElementAdapter<String[], Expression>(annotationAdapter, elementName, removeAnnotationWhenEmpty, buildExpressionConverter(removeArrayInitializerWhenEmpty)));
+		this(new ConversionDeclarationAnnotationElementAdapter<String[]>(annotationAdapter, elementName, removeAnnotationWhenEmpty, buildExpressionConverter(removeArrayInitializerWhenEmpty)));
 	}
 
-	private static ExpressionConverter<String[], Expression> buildExpressionConverter(boolean removeArrayInitializerWhenEmpty) {
-		return new AnnotationStringArrayExpressionConverter<Name>(NameStringExpressionConverter.instance(), removeArrayInitializerWhenEmpty);
+	private static ExpressionConverter<String[]> buildExpressionConverter(boolean removeArrayInitializerWhenEmpty) {
+		return new AnnotationStringArrayExpressionConverter(NameStringExpressionConverter.instance(), removeArrayInitializerWhenEmpty);
 	}
 
-	protected EnumArrayDeclarationAnnotationElementAdapter(ConversionDeclarationAnnotationElementAdapter<String[], Expression> adapter) {
+	protected EnumArrayDeclarationAnnotationElementAdapter(ConversionDeclarationAnnotationElementAdapter<String[]> adapter) {
 		super();
 		this.adapter = adapter;
 	}
@@ -100,13 +99,13 @@
 	 * or
 	 *     FOO
 	 */
-	protected String[] resolve(Expression enumsExpression, ModifiedDeclaration declaration) {
-		if (enumsExpression == null) {
+	protected String[] resolve(Expression expression, ModifiedDeclaration declaration) {
+		if (expression == null) {
 			return EMPTY_STRING_ARRAY;
-		} else if (enumsExpression.getNodeType() == ASTNode.ARRAY_INITIALIZER) {
-			return this.resolveArray((ArrayInitializer) enumsExpression, declaration);
+		} else if (expression.getNodeType() == ASTNode.ARRAY_INITIALIZER) {
+			return this.resolveArray((ArrayInitializer) expression, declaration);
 		} else {
-			return this.resolveSingleElement(enumsExpression, declaration);
+			return this.resolveSingleElement(expression, declaration);
 		}
 	}
 
@@ -115,17 +114,17 @@
 		int len = expressions.size();
 		String[] enums = new String[len];
 		for (int i = len; i-- > 0; ) {
-			enums[i] = this.resolveEnum(expressions.get(i), declaration);
+			enums[i] = this.resolveEnum(expressions.get(i));
 		}
 		return enums;
 	}
 
 	protected String[] resolveSingleElement(Expression enumExpression, ModifiedDeclaration declaration) {
-		return new String[] {this.resolveEnum(enumExpression, declaration)};
+		return new String[] {this.resolveEnum(enumExpression)};
 	}
 
-	protected String resolveEnum(Expression enumExpression, ModifiedDeclaration declaration) {
-		return JDTTools.resolveEnum(declaration.iCompilationUnit(), enumExpression);
+	protected String resolveEnum(Expression expression) {
+		return JDTTools.resolveEnum(expression);
 	}
 
 	@SuppressWarnings("unchecked")
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/EnumDeclarationAnnotationElementAdapter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/EnumDeclarationAnnotationElementAdapter.java
index 838860f..2f0c1f7 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/EnumDeclarationAnnotationElementAdapter.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/EnumDeclarationAnnotationElementAdapter.java
@@ -23,7 +23,7 @@
 	/**
 	 * The wrapped adapter that returns and takes name strings (enums).
 	 */
-	private final ConversionDeclarationAnnotationElementAdapter<String, Name> adapter;
+	private final ConversionDeclarationAnnotationElementAdapter<String> adapter;
 
 
 	// ********** constructors **********
@@ -45,10 +45,10 @@
 	}
 
 	public EnumDeclarationAnnotationElementAdapter(DeclarationAnnotationAdapter annotationAdapter, String elementName, boolean removeAnnotationWhenEmpty) {
-		this(new ConversionDeclarationAnnotationElementAdapter<String, Name>(annotationAdapter, elementName, removeAnnotationWhenEmpty, NameStringExpressionConverter.instance()));
+		this(new ConversionDeclarationAnnotationElementAdapter<String>(annotationAdapter, elementName, removeAnnotationWhenEmpty, NameStringExpressionConverter.instance()));
 	}
 
-	protected EnumDeclarationAnnotationElementAdapter(ConversionDeclarationAnnotationElementAdapter<String, Name> adapter) {
+	protected EnumDeclarationAnnotationElementAdapter(ConversionDeclarationAnnotationElementAdapter<String> adapter) {
 		super();
 		this.adapter = adapter;
 	}
@@ -57,7 +57,7 @@
 	// ********** DeclarationAnnotationElementAdapter implementation **********
 
 	public String getValue(ModifiedDeclaration declaration) {
-		return this.resolve(this.adapter.expression(declaration), declaration);
+		return this.resolve(this.adapter.expression(declaration));
 	}
 
 	public void setValue(String value, ModifiedDeclaration declaration) {
@@ -78,8 +78,8 @@
 	/**
 	 * resolve the enum
 	 */
-	protected String resolve(Expression enumExpression, ModifiedDeclaration declaration) {
-		return (enumExpression == null) ? null : JDTTools.resolveEnum(declaration.iCompilationUnit(), enumExpression);
+	protected String resolve(Expression expression) {
+		return JDTTools.resolveEnum(expression);
 	}
 
 	/**
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/ExpressionConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/ExpressionConverter.java
index 4bce434..fce8284 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/ExpressionConverter.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/ExpressionConverter.java
@@ -15,10 +15,9 @@
 /**
  * Define the protocol for converting an AST expression back and forth
  * from an arbitrary type (e.g. StringLiteral <=> String).
- * E is the expression type.
  * T is the type of the object to be converted to and from an expression.
  */
-public interface ExpressionConverter<T, E extends Expression> {
+public interface ExpressionConverter<T> {
 
 	/**
 	 * Convert the specified object to an
@@ -26,12 +25,12 @@
 	 * The type of the object is determined by the
 	 * contract specified by the client.
 	 */
-	E convert(T object, AST ast);
+	Expression convert(T object, AST ast);
 
 	/**
 	 * Convert the specified expression to an object of some
 	 * pre-determined type.
 	 */
-	T convert(E expression);
+	T convert(Expression expression);
 
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/JDTTools.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/JDTTools.java
index 3491df0..5c513e6 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/JDTTools.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/JDTTools.java
@@ -9,84 +9,85 @@
  ******************************************************************************/
 package org.eclipse.jpt.core.internal.jdtutility;
 
-import org.eclipse.jdt.core.Flags;
 import org.eclipse.jdt.core.IClassFile;
 import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.IImportDeclaration;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.IMember;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jdt.core.JavaModelException;
 import org.eclipse.jdt.core.Signature;
-import org.eclipse.jdt.core.compiler.CategorizedProblem;
 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.CompilationUnit;
 import org.eclipse.jdt.core.dom.Expression;
-import org.eclipse.jdt.internal.codeassist.ISelectionRequestor;
-import org.eclipse.jdt.internal.codeassist.SelectionEngine;
-import org.eclipse.jdt.internal.core.DefaultWorkingCopyOwner;
-import org.eclipse.jdt.internal.core.JavaProject;
-import org.eclipse.jdt.internal.core.SearchableEnvironment;
+import org.eclipse.jdt.core.dom.IBinding;
+import org.eclipse.jdt.core.dom.IVariableBinding;
+import org.eclipse.jdt.core.dom.Name;
 import org.eclipse.jpt.core.internal.JptCorePlugin;
 
 public class JDTTools {
 
+	// TODO get rid of the "lightweight" methods after reworking how
+	// ValidationMessages determine line numbers
 	/**
-	 * add a "normal" import, as opposed to a "static" import
+	 * Build an AST for the specified member's compilation unit or
+	 * (source-attached) class file. Build the AST without its bindings
+	 * resolved.
 	 */
-	public static IImportDeclaration addImport(ICompilationUnit compilationUnit, String importElement) {
-		return addImport(compilationUnit, importElement, Flags.AccDefault);
+	public static CompilationUnit buildLightweightASTRoot(IMember member) {
+		return buildASTRoot(member, false);
 	}
 
 	/**
-	 * this doesn't work yet... see eclipse bugzilla 143684
+	 * Build an AST for the specified member's compilation unit or
+	 * (source-attached) class file. Build the AST with its bindings
+	 * resolved (and the resultant performance hit).
 	 */
-	public static IImportDeclaration addStaticImport(ICompilationUnit compilationUnit, String importElement) {
-		return addImport(compilationUnit, importElement, Flags.AccStatic);
-	}
-
-	public static IImportDeclaration addImport(ICompilationUnit compilationUnit, String importElement, int flags) {
-		try {
-			return compilationUnit.createImport(importElement, null, flags, null);  // null = place at end of import list; null = no progress monitor
-		} catch (JavaModelException ex) {
-			throw new RuntimeException(ex);
-		}
+	public static CompilationUnit buildASTRoot(IMember member) {
+		return buildASTRoot(member, true);
 	}
 
 	/**
-	 * Build an AST for the specified member's compilation unit or class file.
+	 * Build an AST for the specified member's compilation unit or
+	 * (source-attached) class file.
 	 */
-	public static CompilationUnit createASTRoot(IMember member) {
+	private static CompilationUnit buildASTRoot(IMember member, boolean resolveBindings) {
 		return (member.isBinary()) ?
-			createASTRoot(member.getClassFile())  // the class file must have a source attachment
+			buildASTRoot(member.getClassFile(), resolveBindings)  // the class file must have a source attachment
 		:
-			createASTRoot(member.getCompilationUnit());
+			buildASTRoot(member.getCompilationUnit(), resolveBindings);
 	}
 	
-	public static CompilationUnit createASTRoot(IClassFile classFile) {
+	public static CompilationUnit buildASTRoot(IClassFile classFile) {
+		return buildASTRoot(classFile, true);
+	}
+	
+	private static CompilationUnit buildASTRoot(IClassFile classFile, boolean resolveBindings) {
 		ASTParser parser = ASTParser.newParser(AST.JLS3);
 		parser.setSource(classFile);
+		parser.setResolveBindings(resolveBindings);
 		return (CompilationUnit) parser.createAST(null);
-		
 	}
 	
-	public static CompilationUnit createASTRoot(ICompilationUnit compilationUnit) {
+	public static CompilationUnit buildASTRoot(ICompilationUnit compilationUnit) {
+		return buildASTRoot(compilationUnit, true);
+	}
+	
+	private static CompilationUnit buildASTRoot(ICompilationUnit compilationUnit, boolean resolveBindings) {
 		ASTParser parser = ASTParser.newParser(AST.JLS3);
 		parser.setSource(compilationUnit);
+		parser.setResolveBindings(resolveBindings);
 		return (CompilationUnit) parser.createAST(null);
 	}
 	
 	public static IType findType(String packageName, String qualifiedTypeName, IJavaProject javaProject) {
 		try {
-			if (javaProject != null) {
-				return javaProject.findType(packageName, qualifiedTypeName.replace('$', '.'));
-			}
-		} 
-		catch (JavaModelException jme) {
-			JptCorePlugin.log(jme);
+			return javaProject.findType(packageName, qualifiedTypeName.replace('$', '.'));
+		} catch (JavaModelException ex) {
+			JptCorePlugin.log(ex);
+			return null;
 		}
-		return null;
 	}
 
 	/**
@@ -117,7 +118,7 @@
 	}
 
 	/**
-	 * Resolve the specified type name in the scope of the specified jdt type.
+	 * Resolve the specified type name in the scope of the specified JDT type.
 	 * Return the fully-qualified type name or return null if it cannot be
 	 * resolved unambiguously.
 	 */
@@ -149,71 +150,29 @@
 		return Signature.getTypeSignatureKind(signature) == Signature.BASE_TYPE_SIGNATURE;
 	}
 
-	public static String resolveEnum(ICompilationUnit sourceUnit, Expression enumExpression) {
-		return resolveEnum(sourceUnit, enumExpression.getStartPosition(), enumExpression.getStartPosition() + enumExpression.getLength() - 1);
-	}
-
-	public static String resolveEnum(ICompilationUnit sourceUnit, int enumSourceStart, int enumSourceEnd) {
-		try {
-			return resolveEnum_(sourceUnit, enumSourceStart, enumSourceEnd);
-		} catch (JavaModelException ex) {
-			throw new RuntimeException(ex);
-		}
-	}
-
-	private static String resolveEnum_(ICompilationUnit sourceUnit, int enumSourceStart, int enumSourceEnd) throws JavaModelException {
-		String[][] resolvedEnums = resolveField_((org.eclipse.jdt.internal.core.CompilationUnit) sourceUnit, enumSourceStart, enumSourceEnd);
-		// if more than one resolved enum is returned, the enum name is ambiguous
-		if (resolvedEnums == null) {
+	public static String resolveEnum(Expression expression) {
+		if (expression == null) {
 			return null;
 		}
-		if (resolvedEnums.length > 1) {
-			return null;
+		switch (expression.getNodeType()) {
+			case ASTNode.QUALIFIED_NAME:
+			case ASTNode.SIMPLE_NAME:
+				return resolveEnum((Name) expression);
+			default:
+				return null;
 		}
-		return resolvedEnums[0][0] + "." + resolvedEnums[0][1] + "." + resolvedEnums[0][2];
 	}
 
-	// code lifted from SourceType.resolveType(String, WorkingCopyOwner)
-	private static String[][] resolveField_(org.eclipse.jdt.internal.core.CompilationUnit sourceUnit, int selectionSourceStart, int selectionSourceEnd) throws JavaModelException {
-		class TypeResolveRequestor implements ISelectionRequestor {
-			String[][] answers = null;
-			public void acceptType(char[] packageName, char[] tName, int modifiers, boolean isDeclaration, char[] uniqueKey, int start, int end) {
-				// ignore
-			}
-			public void acceptError(CategorizedProblem error) {
-				// ignore
-			}
-			public void acceptField(char[] declaringTypePackageName, char[] declaringTypeName, char[] fieldName, boolean isDeclaration, char[] uniqueKey, int start, int end) {
-				String[] answer = new String[]  {new String(declaringTypePackageName), new String(declaringTypeName), new String(fieldName) };
-				if (this.answers == null) {
-					this.answers = new String[][]{ answer };
-				} else {
-					int len = this.answers.length;
-					System.arraycopy(this.answers, 0, this.answers = new String[len+1][], 0, len);
-					this.answers[len] = answer;
-				}
-			}
-			public void acceptMethod(char[] declaringTypePackageName, char[] declaringTypeName, String enclosingDeclaringTypeSignature, char[] selector, char[][] parameterPackageNames, char[][] parameterTypeNames, String[] parameterSignatures, char[][] typeParameterNames, char[][][] typeParameterBoundNames, boolean isConstructor, boolean isDeclaration, char[] uniqueKey, int start, int end) {
-				// ignore
-			}
-			public void acceptPackage(char[] packageName){
-				// ignore
-			}
-			public void acceptTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] typeParameterName, boolean isDeclaration, int start, int end) {
-				// ignore
-			}
-			public void acceptMethodTypeParameter(char[] declaringTypePackageName, char[] declaringTypeName, char[] selector, int selectorStart, int selcetorEnd, char[] typeParameterName, boolean isDeclaration, int start, int end) {
-				// ignore
-			}
-	
+	public static String resolveEnum(Name enumExpression) {
+		IBinding binding = enumExpression.resolveBinding();
+		if (binding == null) {
+			return null;  // TODO figure why this is null sometimes
 		}
-		TypeResolveRequestor requestor = new TypeResolveRequestor();
-		JavaProject project = (JavaProject) sourceUnit.getJavaProject();
-		SearchableEnvironment environment = project.newSearchableNameEnvironment(DefaultWorkingCopyOwner.PRIMARY);
-	
-		SelectionEngine engine = new SelectionEngine(environment, requestor, project.getOptions(true));
-			
-		engine.select(sourceUnit, selectionSourceStart, selectionSourceEnd);
-		return requestor.answers;
+		if (binding.getKind() != IBinding.VARIABLE) {
+			return null;
+		}
+		IVariableBinding variableBinding = (IVariableBinding) binding;
+		return variableBinding.getType().getQualifiedName() + "." + variableBinding.getName();
 	}
+
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/Member.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/Member.java
index 2ea7212..e1ee7ec 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/Member.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/Member.java
@@ -96,7 +96,14 @@
 	 * note: this creates a *new* AST
 	 */
 	public CompilationUnit astRoot() {
-		return JDTTools.createASTRoot(this.jdtMember);
+		return JDTTools.buildASTRoot(this.jdtMember);
+	}
+
+	/**
+	 * note: this creates a *new* AST
+	 */
+	private CompilationUnit lightweightASTRoot() {
+		return JDTTools.buildLightweightASTRoot(this.jdtMember);
 	}
 
 	public ModifiedDeclaration modifiedDeclaration() {
@@ -112,7 +119,7 @@
 	}
 
 	public ITextRange textRange() {
-		return this.textRange(this.astRoot());
+		return this.textRange(this.lightweightASTRoot());
 	}
 
 	public ITextRange textRange(CompilationUnit astRoot) {
@@ -124,23 +131,23 @@
 	}
 
 	public ITextRange nameTextRange() {
-		return this.nameTextRange(this.astRoot());
+		return this.nameTextRange(this.lightweightASTRoot());
 	}
 	
 	public ITextRange nameTextRange(CompilationUnit astRoot) {
 		ISourceRange sourceRange = this.nameSourceRange();
-		return 
+		return
 			new SimpleTextRange(
 				sourceRange.getOffset(), 
 				sourceRange.getLength(),
-				astRoot.getLineNumber(sourceRange.getOffset()));
+				astRoot.getLineNumber(sourceRange.getOffset())
+			);
 	}
 	
 	private ISourceRange nameSourceRange() {
 		try {
-			return getJdtMember().getNameRange();
-		}
-		catch (JavaModelException ex) {
+			return this.jdtMember.getNameRange();
+		} catch (JavaModelException ex) {
 			throw new RuntimeException(ex);
 		}
 	}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/ModifiedDeclaration.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/ModifiedDeclaration.java
index 18c8520..9af69a2 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/ModifiedDeclaration.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/ModifiedDeclaration.java
@@ -20,6 +20,7 @@
 import org.eclipse.jdt.core.dom.BodyDeclaration;
 import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jdt.core.dom.IExtendedModifier;
+import org.eclipse.jdt.core.dom.ITypeBinding;
 import org.eclipse.jdt.core.dom.ImportDeclaration;
 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
 import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
@@ -71,7 +72,7 @@
 	 * Return the "declaration" AST node.
 	 */
 	public ASTNode getDeclaration() {
-		return this.adapter.getDeclaration();
+		return this.adapter.declaration();
 	}
 
 	/**
@@ -277,19 +278,30 @@
 	}
 
 	private String qualifiedName(Annotation annotation) {
-		String name = annotation.getTypeName().getFullyQualifiedName();
-		if (name.indexOf('.') != -1) {
-			return name;  // name is already qualified
-		}
-		String resolvedName = JDTTools.resolve(name, this.type());
-		if (resolvedName != null) {
-			return resolvedName;
+		ITypeBinding typeBinding = annotation.resolveTypeBinding();
+		if (typeBinding != null) {
+			String resolvedName = typeBinding.getQualifiedName();
+			if (resolvedName != null) {
+				return resolvedName;
+			}
 		}
 		// hack(?): check for a matching import because when moving a stand-alone
 		// annotation to its container in CombinationIndexedDeclarationAnnotationAdapter
 		// the container's import is added but then it won't "resolve" upon
 		// subsequent lookups... :-(
-		return this.importFor(name);  // look for a matching import
+		return this.importFor(annotation.getTypeName().getFullyQualifiedName());  // look for a matching import
+
+		// OLD METHOD SOURCE:
+//		String name = annotation.getTypeName().getFullyQualifiedName();
+//		if (name.indexOf('.') != -1) {
+//			return name;  // name is already qualified
+//		}
+//		String resolvedName = JDTTools.resolve(name, this.type());
+//		// hack(?): check for a matching import because when moving a stand-alone
+//		// annotation to its container in CombinationIndexedDeclarationAnnotationAdapter
+//		// the container's import is added but then it won't "resolve" upon
+//		// subsequent lookups... :-(
+//		return this.importFor(name);  // look for a matching import
 	}
 
 	/**
@@ -353,7 +365,7 @@
 		/**
 		 * Return the adapted "declaration".
 		 */
-		ASTNode getDeclaration();
+		ASTNode declaration();
 
 		/**
 		 * Return the "declaration"'s list of modifiers.
@@ -369,7 +381,7 @@
 			super();
 			this.declaration = declaration;
 		}
-		public ASTNode getDeclaration() {
+		public ASTNode declaration() {
 			return this.declaration;
 		}
 		@SuppressWarnings("unchecked")
@@ -388,7 +400,7 @@
 			super();
 			this.declaration = declaration;
 		}
-		public ASTNode getDeclaration() {
+		public ASTNode declaration() {
 			return this.declaration;
 		}
 		@SuppressWarnings("unchecked")
@@ -407,7 +419,7 @@
 			super();
 			this.declaration = declaration;
 		}
-		public ASTNode getDeclaration() {
+		public ASTNode declaration() {
 			return this.declaration;
 		}
 		@SuppressWarnings("unchecked")
@@ -426,7 +438,7 @@
 			super();
 			this.declaration = declaration;
 		}
-		public ASTNode getDeclaration() {
+		public ASTNode declaration() {
 			return this.declaration;
 		}
 		@SuppressWarnings("unchecked")
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/NameStringExpressionConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/NameStringExpressionConverter.java
index 078835e..0aaa703 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/NameStringExpressionConverter.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/NameStringExpressionConverter.java
@@ -11,6 +11,7 @@
 
 import org.eclipse.jdt.core.dom.AST;
 import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Expression;
 import org.eclipse.jdt.core.dom.Name;
 
 /**
@@ -18,14 +19,14 @@
  * (e.g. "com.xxx.Foo.VALUE1" or "value").
  */
 public final class NameStringExpressionConverter
-	extends AbstractExpressionConverter<String, Name>
+	extends AbstractExpressionConverter<String>
 {
-	private static ExpressionConverter<String, Name> INSTANCE;
+	private static ExpressionConverter<String> INSTANCE;
 
 	/**
 	 * Return the singleton.
 	 */
-	public static ExpressionConverter<String, Name> instance() {
+	public static ExpressionConverter<String> instance() {
 		if (INSTANCE == null) {
 			INSTANCE = new NameStringExpressionConverter();
 		}
@@ -40,16 +41,16 @@
 	}
 
 	@Override
-	protected Name convert_(String string, AST ast) {
+	protected Name convertObject(String string, AST ast) {
 		return ast.newName(string);
 	}
 
 	@Override
-	protected String convert_(Name name) {
-		switch (name.getNodeType()) {
+	protected String convertExpression(Expression expression) {
+		switch (expression.getNodeType()) {
 			case ASTNode.QUALIFIED_NAME:
 			case ASTNode.SIMPLE_NAME:
-				return name.getFullyQualifiedName();
+				return ((Name) expression).getFullyQualifiedName();
 			default:
 				return null;
 		}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/NullExpressionConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/NullExpressionConverter.java
index e58f3af..b45c0ce 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/NullExpressionConverter.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/NullExpressionConverter.java
@@ -17,16 +17,16 @@
  * No conversion.
  */
 public final class NullExpressionConverter
-	implements ExpressionConverter<Expression, Expression>
+	implements ExpressionConverter<Expression>
 {
 
 	// singleton
-	private static ExpressionConverter<Expression, Expression> INSTANCE = new NullExpressionConverter();
+	private static ExpressionConverter<Expression> INSTANCE = new NullExpressionConverter();
 
 	/**
 	 * Return the singleton.
 	 */
-	public static ExpressionConverter<Expression, Expression> instance() {
+	public static ExpressionConverter<Expression> instance() {
 		if (INSTANCE == null) {
 			INSTANCE = new NullExpressionConverter();
 		}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/NumberStringExpressionConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/NumberStringExpressionConverter.java
index 0b312fb..ead2da9 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/NumberStringExpressionConverter.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/NumberStringExpressionConverter.java
@@ -10,7 +10,7 @@
 package org.eclipse.jpt.core.internal.jdtutility;
 
 import org.eclipse.jdt.core.dom.AST;
-import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Expression;
 import org.eclipse.jdt.core.dom.NumberLiteral;
 
 /**
@@ -18,14 +18,14 @@
  * (e.g. "48").
  */
 public final class NumberStringExpressionConverter
-	extends AbstractExpressionConverter<String, NumberLiteral>
+	extends AbstractExpressionConverter<String>
 {
-	private static ExpressionConverter<String, NumberLiteral> INSTANCE;
+	private static ExpressionConverter<String> INSTANCE;
 
 	/**
 	 * Return the singleton.
 	 */
-	public static ExpressionConverter<String, NumberLiteral> instance() {
+	public static ExpressionConverter<String> instance() {
 		if (INSTANCE == null) {
 			INSTANCE = new NumberStringExpressionConverter();
 		}
@@ -40,16 +40,14 @@
 	}
 	
 	@Override
-	protected NumberLiteral convert_(String string, AST ast) {
+	protected NumberLiteral convertObject(String string, AST ast) {
 		return ast.newNumberLiteral(string);
 	}
 
 	@Override
-	protected String convert_(NumberLiteral numberLiteral) {
-		return (numberLiteral.getNodeType() == ASTNode.NUMBER_LITERAL) ?
-			numberLiteral.getToken()
-		:
-			null;
+	protected String convertExpression(Expression expression) {
+		Object value = expression.resolveConstantExpressionValue();
+		return (value instanceof Number) ? ((Number) value).toString() : null;
 	}
 
 }
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/PrimitiveTypeStringExpressionConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/PrimitiveTypeStringExpressionConverter.java
index 49f6d99..910d735 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/PrimitiveTypeStringExpressionConverter.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/PrimitiveTypeStringExpressionConverter.java
@@ -11,6 +11,7 @@
 
 import org.eclipse.jdt.core.dom.AST;
 import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Expression;
 import org.eclipse.jdt.core.dom.PrimitiveType;
 import org.eclipse.jdt.core.dom.TypeLiteral;
 
@@ -19,14 +20,14 @@
  * (e.g. "int").
  */
 public final class PrimitiveTypeStringExpressionConverter
-	extends AbstractExpressionConverter<String, TypeLiteral>
+	extends AbstractExpressionConverter<String>
 {
-	private static ExpressionConverter<String, TypeLiteral> INSTANCE;
+	private static ExpressionConverter<String> INSTANCE;
 
 	/**
 	 * Return the singleton.
 	 */
-	public static ExpressionConverter<String, TypeLiteral> instance() {
+	public static ExpressionConverter<String> instance() {
 		if (INSTANCE == null) {
 			INSTANCE = new PrimitiveTypeStringExpressionConverter();
 		}
@@ -41,7 +42,7 @@
 	}
 
 	@Override
-	protected TypeLiteral convert_(String string, AST ast) {
+	protected TypeLiteral convertObject(String string, AST ast) {
 		org.eclipse.jdt.core.dom.Type type = ast.newPrimitiveType(PrimitiveType.toCode(string));
 		TypeLiteral typeLiteral = ast.newTypeLiteral();
 		typeLiteral.setType(type);
@@ -49,9 +50,9 @@
 	}
 
 	@Override
-	protected String convert_(TypeLiteral typeLiteral) {
-		if (typeLiteral.getNodeType() == ASTNode.TYPE_LITERAL) {
-			org.eclipse.jdt.core.dom.Type type = typeLiteral.getType();
+	protected String convertExpression(Expression expression) {
+		if (expression.getNodeType() == ASTNode.TYPE_LITERAL) {
+			org.eclipse.jdt.core.dom.Type type = ((TypeLiteral) expression).getType();
 			if (type.getNodeType() == ASTNode.PRIMITIVE_TYPE) {
 				return ((PrimitiveType) type).getPrimitiveTypeCode().toString();
 			}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/SimpleTypeStringExpressionConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/SimpleTypeStringExpressionConverter.java
index 43566cb..e596a33 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/SimpleTypeStringExpressionConverter.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/SimpleTypeStringExpressionConverter.java
@@ -11,6 +11,7 @@
 
 import org.eclipse.jdt.core.dom.AST;
 import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Expression;
 import org.eclipse.jdt.core.dom.Name;
 import org.eclipse.jdt.core.dom.SimpleType;
 import org.eclipse.jdt.core.dom.TypeLiteral;
@@ -20,14 +21,14 @@
  * (e.g. "java.lang.Object").
  */
 public final class SimpleTypeStringExpressionConverter
-	extends AbstractExpressionConverter<String, TypeLiteral>
+	extends AbstractExpressionConverter<String>
 {
-	private static ExpressionConverter<String, TypeLiteral> INSTANCE;
+	private static ExpressionConverter<String> INSTANCE;
 
 	/**
 	 * Return the singleton.
 	 */
-	public static ExpressionConverter<String, TypeLiteral> instance() {
+	public static ExpressionConverter<String> instance() {
 		if (INSTANCE == null) {
 			INSTANCE = new SimpleTypeStringExpressionConverter();
 		}
@@ -42,7 +43,7 @@
 	}
 
 	@Override
-	protected TypeLiteral convert_(String string, AST ast) {
+	protected TypeLiteral convertObject(String string, AST ast) {
 		Name name = ast.newName(string);
 		org.eclipse.jdt.core.dom.Type type = ast.newSimpleType(name);
 		TypeLiteral typeLiteral = ast.newTypeLiteral();
@@ -51,9 +52,9 @@
 	}
 
 	@Override
-	protected String convert_(TypeLiteral typeLiteral) {
-		if (typeLiteral.getNodeType() == ASTNode.TYPE_LITERAL) {
-			org.eclipse.jdt.core.dom.Type type = typeLiteral.getType();
+	protected String convertExpression(Expression expression) {
+		if (expression.getNodeType() == ASTNode.TYPE_LITERAL) {
+			org.eclipse.jdt.core.dom.Type type = ((TypeLiteral) expression).getType();
 			if (type.getNodeType() == ASTNode.SIMPLE_TYPE) {
 				return ((SimpleType) type).getName().getFullyQualifiedName();
 			}
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/StringArrayExpressionConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/StringArrayExpressionConverter.java
index 02d081a..31d61ab 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/StringArrayExpressionConverter.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/StringArrayExpressionConverter.java
@@ -10,23 +10,28 @@
 package org.eclipse.jpt.core.internal.jdtutility;
 
 import java.util.List;
+
 import org.eclipse.jdt.core.dom.AST;
+import org.eclipse.jdt.core.dom.ASTNode;
 import org.eclipse.jdt.core.dom.ArrayInitializer;
 import org.eclipse.jdt.core.dom.Expression;
 
 /**
  * Convert an array initializer to/from an array of strings (e.g. {"text0", "text1"}).
- * E is the type of the expressions to be found in the array initializer.
  * 
  * Do NOT use this class for converting array initializers in annotation elements.
  * Java5 has a bit of syntactic sugar that allows a single-element array
- * initializer to not have curly braces. This converter will barf if it encounters
+ * initializer to not have curly braces. This converter will return null if it encounters
  * anything other than an array initializer.
+ * 
+ * Invalid entries in the array initializer will result in null elements in the
+ * resulting string array. This allows clients to manipulate elements at
+ * the appropriate index.
  */
-public class StringArrayExpressionConverter<E extends Expression>
-	extends AbstractExpressionConverter<String[], ArrayInitializer>
+public class StringArrayExpressionConverter
+	extends AbstractExpressionConverter<String[]>
 {
-	private final ExpressionConverter<String, E> elementConverter;
+	private final ExpressionConverter<String> elementConverter;
 	private final boolean removeArrayInitializerWhenEmpty;
 
 	private static final String[] EMPTY_STRING_ARRAY = new String[0];
@@ -35,11 +40,11 @@
 	/**
 	 * The default behavior is to remove the array initializer if it is empty.
 	 */
-	public StringArrayExpressionConverter(ExpressionConverter<String, E> elementConverter) {
+	public StringArrayExpressionConverter(ExpressionConverter<String> elementConverter) {
 		this(elementConverter, true);
 	}
 
-	public StringArrayExpressionConverter(ExpressionConverter<String, E> elementConverter, boolean removeArrayInitializerWhenEmpty) {
+	public StringArrayExpressionConverter(ExpressionConverter<String> elementConverter, boolean removeArrayInitializerWhenEmpty) {
 		super();
 		this.elementConverter = elementConverter;
 		this.removeArrayInitializerWhenEmpty = removeArrayInitializerWhenEmpty;
@@ -50,7 +55,7 @@
 	 * this method is 'public' so it can be called by
 	 * AnnotationStringArrayExpressionConverter
 	 */
-	public ArrayInitializer convert_(String[] strings, AST ast) {
+	public ArrayInitializer convertObject(String[] strings, AST ast) {
 		if ((strings.length == 0) && this.removeArrayInitializerWhenEmpty) {
 			return null;
 		}
@@ -67,21 +72,29 @@
 		return arrayInitializer.expressions();
 	}
 
-	@Override
 	/*
 	 * this method is 'public' so it can be called by
 	 * AnnotationStringArrayExpressionConverter
 	 */
+	@Override
 	public String[] convertNull() {
 		return EMPTY_STRING_ARRAY;
 	}
 
 	@Override
+	protected String[] convertExpression(Expression expression) {
+		return (expression.getNodeType() == ASTNode.ARRAY_INITIALIZER) ?
+				this.convertArrayInitializer((ArrayInitializer) expression)
+			:
+				EMPTY_STRING_ARRAY;
+	}
+
 	/*
-	 * 'public' in support of AnnotationStringArrayExpressionConverter
+	 * this method is 'public' so it can be called by
+	 * AnnotationStringArrayExpressionConverter
 	 */
-	public String[] convert_(ArrayInitializer arrayInitializer) {
-		List<E> expressions = this.downcastExpressions(arrayInitializer);
+	public String[] convertArrayInitializer(ArrayInitializer arrayInitializer) {
+		List<Expression> expressions = this.downcastExpressions(arrayInitializer);
 		int len = expressions.size();
 		String[] strings = new String[len];
 		for (int i = len; i-- > 0; ) {
@@ -91,7 +104,7 @@
 	}
 
 	@SuppressWarnings("unchecked")
-	private List<E> downcastExpressions(ArrayInitializer arrayInitializer) {
+	private List<Expression> downcastExpressions(ArrayInitializer arrayInitializer) {
 		return arrayInitializer.expressions();
 	}
 
diff --git a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/StringExpressionConverter.java b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/StringExpressionConverter.java
index 444650f..9560ca2 100644
--- a/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/StringExpressionConverter.java
+++ b/jpa/plugins/org.eclipse.jpt.core/src/org/eclipse/jpt/core/internal/jdtutility/StringExpressionConverter.java
@@ -10,21 +10,21 @@
 package org.eclipse.jpt.core.internal.jdtutility;
 
 import org.eclipse.jdt.core.dom.AST;
-import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.Expression;
 import org.eclipse.jdt.core.dom.StringLiteral;
 
 /**
  * Convert a string literal to/from a string (e.g. "text").
  */
 public final class StringExpressionConverter
-	extends AbstractExpressionConverter<String, StringLiteral>
+	extends AbstractExpressionConverter<String>
 {
-	private static ExpressionConverter<String, StringLiteral> INSTANCE;
+	private static ExpressionConverter<String> INSTANCE;
 
 	/**
 	 * Return the singleton.
 	 */
-	public static ExpressionConverter<String, StringLiteral> instance() {
+	public static ExpressionConverter<String> instance() {
 		if (INSTANCE == null) {
 			INSTANCE = new StringExpressionConverter();
 		}
@@ -39,18 +39,16 @@
 	}
 
 	@Override
-	protected StringLiteral convert_(String string, AST ast) {
+	protected StringLiteral convertObject(String string, AST ast) {
 		StringLiteral stringLiteral = ast.newStringLiteral();
 		stringLiteral.setLiteralValue(string);
 		return stringLiteral;
 	}
 
 	@Override
-	protected String convert_(StringLiteral stringLiteral) {
-		return (stringLiteral.getNodeType() == ASTNode.STRING_LITERAL) ?
-			stringLiteral.getLiteralValue()
-		:
-			null;
+	protected String convertExpression(Expression expression) {
+		Object value = expression.resolveConstantExpressionValue();
+		return (value instanceof String) ? (String) value : null;
 	}
 
 }
diff --git a/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jdtutility/JDTToolsTests.java b/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jdtutility/JDTToolsTests.java
index 5176595..1e22611 100644
--- a/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jdtutility/JDTToolsTests.java
+++ b/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jdtutility/JDTToolsTests.java
@@ -10,6 +10,7 @@
 package org.eclipse.jpt.core.tests.internal.jdtutility;
 
 import org.eclipse.jdt.core.Signature;
+import org.eclipse.jdt.core.dom.Name;
 import org.eclipse.jpt.core.internal.jdtutility.ConversionDeclarationAnnotationElementAdapter;
 import org.eclipse.jpt.core.internal.jdtutility.DeclarationAnnotationAdapter;
 import org.eclipse.jpt.core.internal.jdtutility.DeclarationAnnotationElementAdapter;
@@ -118,7 +119,7 @@
 		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forStrings(daa, "foo");
 		FieldAttribute field = this.idField();
 
-		String actual = JDTTools.resolveEnum(this.jdtType().getCompilationUnit(), field.annotationElementExpression(daea));
+		String actual = JDTTools.resolveEnum((Name) field.annotationElementExpression(daea));
 		assertEquals("enums.TestEnum.BAZ", actual);
 	}
 
@@ -131,7 +132,7 @@
 		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forStrings(daa, "foo");
 		FieldAttribute field = this.idField();
 
-		String actual = JDTTools.resolveEnum(this.jdtType().getCompilationUnit(), field.annotationElementExpression(daea));
+		String actual = JDTTools.resolveEnum((Name) field.annotationElementExpression(daea));
 		assertEquals("enums.TestEnum.BAZ", actual);
 	}
 
@@ -144,7 +145,7 @@
 		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forStrings(daa, "foo");
 		FieldAttribute field = this.idField();
 
-		String actual = JDTTools.resolveEnum(this.jdtType().getCompilationUnit(), field.annotationElementExpression(daea));
+		String actual = JDTTools.resolveEnum((Name) field.annotationElementExpression(daea));
 		assertEquals("enums.TestEnum.BAZ", actual);
 	}
 
@@ -157,7 +158,7 @@
 		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forStrings(daa, "foo");
 		FieldAttribute field = this.idField();
 
-		String actual = JDTTools.resolveEnum(this.jdtType().getCompilationUnit(), field.annotationElementExpression(daea));
+		String actual = JDTTools.resolveEnum((Name) field.annotationElementExpression(daea));
 		assertEquals("enums.TestEnum.BAZ", actual);
 	}
 
diff --git a/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jdtutility/MemberAnnotationElementAdapterTests.java b/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jdtutility/MemberAnnotationElementAdapterTests.java
index 9f16dc1..b07c314 100644
--- a/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jdtutility/MemberAnnotationElementAdapterTests.java
+++ b/jpa/tests/org.eclipse.jpt.core.tests/src/org/eclipse/jpt/core/tests/internal/jdtutility/MemberAnnotationElementAdapterTests.java
@@ -11,12 +11,6 @@
 
 import java.util.Arrays;
 
-import org.eclipse.jdt.core.dom.BooleanLiteral;
-import org.eclipse.jdt.core.dom.CharacterLiteral;
-import org.eclipse.jdt.core.dom.Expression;
-import org.eclipse.jdt.core.dom.NumberLiteral;
-import org.eclipse.jdt.core.dom.StringLiteral;
-import org.eclipse.jdt.core.dom.TypeLiteral;
 import org.eclipse.jpt.core.internal.ITextRange;
 import org.eclipse.jpt.core.internal.jdtutility.ASTNodeTextRange;
 import org.eclipse.jpt.core.internal.jdtutility.AnnotationElementAdapter;
@@ -65,7 +59,7 @@
 		this.createAnnotationAndMembers("Foo", "int bar();");
 		this.createTestType("@annot.Foo(bar=48)");
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, NumberLiteral>(daa, "bar", NumberStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa, "bar", NumberStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 		assertEquals("48", aea.getValue());
 	}
@@ -74,7 +68,7 @@
 		this.createAnnotationAndMembers("Foo", "char bar();");
 		this.createTestType("@annot.Foo(bar='c')");
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, CharacterLiteral>(daa, "bar", CharacterStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa, "bar", CharacterStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 		assertEquals("c", aea.getValue());
 	}
@@ -83,7 +77,7 @@
 		this.createAnnotationAndMembers("Foo", "boolean bar();");
 		this.createTestType("@annot.Foo(bar=false)");
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, BooleanLiteral>(daa, "bar", BooleanStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa, "bar", BooleanStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 		assertEquals("false", aea.getValue());
 	}
@@ -96,7 +90,7 @@
 		DeclarationAnnotationAdapter daa1 = new SimpleDeclarationAnnotationAdapter("annot.Foo");
 		DeclarationAnnotationAdapter daa2 = new NestedDeclarationAnnotationAdapter(daa1, "value", "annot.Bar");
 		DeclarationAnnotationAdapter daa3 = new NestedDeclarationAnnotationAdapter(daa2, "jimmy", "annot.Baz");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, BooleanLiteral>(daa3, "fred", BooleanStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa3, "fred", BooleanStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 		assertEquals("false", aea.getValue());
 	}
@@ -105,7 +99,7 @@
 		this.createAnnotationAndMembers("Foo", "boolean value();");
 		this.createTestType("@annot.Foo(false)");
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, BooleanLiteral>(daa, BooleanStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa, BooleanStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 		assertEquals("false", aea.getValue());
 	}
@@ -141,6 +135,197 @@
 		assertNull(aea.getValue());
 	}
 
+	public void testGetValueStringConcatenation() throws Exception {
+		this.createAnnotationAndMembers("Foo", "String bar();");
+		this.createTestType("@annot.Foo(bar=\"xxx\" + \"yyy\" + \"zzz\")");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forStrings(daa, "bar");
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertEquals("xxxyyyzzz", aea.getValue());
+	}
+
+	public void testGetValueStringConstant() throws Exception {
+		this.createAnnotationAndMembers("Foo", "String bar();");
+		// just a bit hacky:
+		this.createTestType("private static final String FOO_BAR = \"xxx\"; @annot.Foo(bar=FOO_BAR + \"yyy\" + \"zzz\")");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forStrings(daa, "bar");
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertEquals("xxxyyyzzz", aea.getValue());
+	}
+
+	public void testGetValueNumberArithmetic() throws Exception {
+		this.createAnnotationAndMembers("Foo", "int bar();");
+		this.createTestType("@annot.Foo(bar=47 - 7 + 2 * 1 / 1)");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forNumbers(daa, "bar");
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertEquals("42", aea.getValue());
+	}
+
+	public void testGetValueNumberShift() throws Exception {
+		this.createAnnotationAndMembers("Foo", "int bar();");
+		this.createTestType("@annot.Foo(bar=2 << 2)");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forNumbers(daa, "bar");
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertEquals("8", aea.getValue());
+	}
+
+	public void testGetValueNumberConstant() throws Exception {
+		this.createAnnotationAndMembers("Foo", "int bar();");
+		// just a bit hacky:
+		this.createTestType("private static final int FOO_BAR = 77; @annot.Foo(bar=FOO_BAR)");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forNumbers(daa, "bar");
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertEquals("77", aea.getValue());
+	}
+
+	public void testGetValueCharacterConstant() throws Exception {
+		this.createAnnotationAndMembers("Foo", "char bar();");
+		// just a bit hacky:
+		this.createTestType("private static final char FOO_BAR = 'Q'; @annot.Foo(bar=FOO_BAR)");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forCharacters(daa, "bar");
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertEquals("Q", aea.getValue());
+	}
+
+	public void testGetValueCharacterCast() throws Exception {
+		this.createAnnotationAndMembers("Foo", "char bar();");
+		this.createTestType("@annot.Foo(bar=(char) 0x41)");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forCharacters(daa, "bar");
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertEquals("A", aea.getValue());
+	}
+
+	public void testGetValueBooleanOperator1() throws Exception {
+		this.createAnnotationAndMembers("Foo", "boolean bar();");
+		this.createTestType("@annot.Foo(bar=7 > 2)");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forBooleans(daa, "bar");
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertEquals("true", aea.getValue());
+	}
+
+	public void testGetValueBooleanOperator2() throws Exception {
+		this.createAnnotationAndMembers("Foo", "boolean bar();");
+		this.createTestType("@annot.Foo(bar=7 == 2)");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forBooleans(daa, "bar");
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertEquals("false", aea.getValue());
+	}
+
+	public void testGetValueBooleanOperator3() throws Exception {
+		this.createAnnotationAndMembers("Foo", "boolean bar();");
+		this.createTestType("@annot.Foo(bar=(7 != 2) && false)");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forBooleans(daa, "bar");
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertEquals("false", aea.getValue());
+	}
+
+	public void testGetValueBooleanOperator4() throws Exception {
+		this.createAnnotationAndMembers("Foo", "boolean bar();");
+		this.createTestType("@annot.Foo(bar=(7 != 2) ? false : true)");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forBooleans(daa, "bar");
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertEquals("false", aea.getValue());
+	}
+
+	public void testGetValueInvalidValue1() throws Exception {
+		this.createAnnotationAndMembers("Foo", "String bar();");
+		this.createTestType("@annot.Foo(bar=77)");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forStrings(daa, "bar");
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertNull(aea.getValue());
+	}
+
+	public void testGetValueInvalidValue2() throws Exception {
+		this.createAnnotationAndMembers("Foo", "String bar();");
+		this.createTestType("@annot.Foo(bar=bazzzz)");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forStrings(daa, "bar");
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertNull(aea.getValue());
+	}
+
+	public void testGetValueInvalidValue3() throws Exception {
+		this.createAnnotationAndMembers("Foo", "boolean bar();");
+		this.createTestType("@annot.Foo(bar=bazzzz)");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forBooleans(daa, "bar");
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertNull(aea.getValue());
+	}
+
+	public void testGetValueInvalidValue4() throws Exception {
+		this.createAnnotationAndMembers("Foo", "char bar();");
+		this.createTestType("@annot.Foo(bar=\"bazzzz\")");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String> daea = ConversionDeclarationAnnotationElementAdapter.forCharacters(daa, "bar");
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertNull(aea.getValue());
+	}
+
+	public void testGetValueInvalidValue5() throws Exception {
+		this.createAnnotationAndMembers("Foo", "Class bar();");
+		this.createTestType("@annot.Foo(bar=\"java.lang.Object\")");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa, "bar", SimpleTypeStringExpressionConverter.instance());
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertNull(aea.getValue());
+	}
+
+	public void testGetValueInvalidValue6() throws Exception {
+		this.createEnum("TestEnum", "XXX, YYY, ZZZ");
+		this.createAnnotationAndMembers("Foo", "enums.TestEnum bar();");
+		this.createTestType("@annot.Foo(bar=enums.TestEnum.class)");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String> daea = new EnumDeclarationAnnotationElementAdapter(daa, "bar");
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertNull(aea.getValue());
+	}
+
+	public void testGetValueInvalidValue7() throws Exception {
+		this.createAnnotationAndMembers("Baz", "boolean fred();");
+		this.createAnnotationAndMembers("Bar", "annot.Baz jimmy();");
+		this.createAnnotationAndMembers("Foo", "annot.Bar value();");
+		String value = "\"false\"";
+		String element = "fred=" + value;
+		String annotation = "@annot.Foo(@annot.Bar(jimmy=@annot.Baz(" + element + ")))";
+		this.createTestType(annotation);
+		DeclarationAnnotationAdapter daa1 = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationAdapter daa2 = new NestedDeclarationAnnotationAdapter(daa1, "value", "annot.Bar");
+		DeclarationAnnotationAdapter daa3 = new NestedDeclarationAnnotationAdapter(daa2, "jimmy", "annot.Baz");
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa3, "fred", BooleanStringExpressionConverter.instance());
+		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
+		assertNull(aea.getValue());
+	}
+
+	public void testGetValueInvalidValue8() throws Exception {
+		this.createAnnotationAndMembers("Foo", "String[] bar();");
+		this.createTestType("@annot.Foo(bar={true, false})");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[]>(daa, "bar", AnnotationStringArrayExpressionConverter.forStrings());
+		AnnotationElementAdapter<String[]> aea = new MemberAnnotationElementAdapter<String[]>(this.idField(), daea);
+		assertTrue(Arrays.equals(new String[] {null, null}, aea.getValue()));
+	}
+
+	public void testGetValueInvalidValue9() throws Exception {
+		this.createAnnotationAndMembers("Foo", "String[] bar();");
+		this.createTestType("@annot.Foo(bar=77)");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[]>(daa, "bar", AnnotationStringArrayExpressionConverter.forStrings());
+		AnnotationElementAdapter<String[]> aea = new MemberAnnotationElementAdapter<String[]>(this.idField(), daea);
+		assertTrue(Arrays.equals(new String[] {null}, aea.getValue()));
+	}
+
 	public void testASTNode1() throws Exception {
 		this.createAnnotationAndMembers("Foo", "String bar();");
 		String value = "\"xxx\"";
@@ -168,7 +353,7 @@
 		DeclarationAnnotationAdapter daa1 = new SimpleDeclarationAnnotationAdapter("annot.Foo");
 		DeclarationAnnotationAdapter daa2 = new NestedDeclarationAnnotationAdapter(daa1, "value", "annot.Bar");
 		DeclarationAnnotationAdapter daa3 = new NestedDeclarationAnnotationAdapter(daa2, "jimmy", "annot.Baz");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, BooleanLiteral>(daa3, "fred", BooleanStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa3, "fred", BooleanStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 		assertEquals("false", aea.getValue());
 		ITextRange textRange = new ASTNodeTextRange(aea.astNode());
@@ -239,7 +424,7 @@
 		DeclarationAnnotationAdapter daa1 = new SimpleDeclarationAnnotationAdapter("annot.Foo");
 		DeclarationAnnotationAdapter daa2 = new NestedDeclarationAnnotationAdapter(daa1, "value", "annot.Bar");
 		DeclarationAnnotationAdapter daa3 = new NestedDeclarationAnnotationAdapter(daa2, "jimmy", "annot.Baz");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, BooleanLiteral>(daa3, "fred", BooleanStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa3, "fred", BooleanStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 
 		aea.setValue(null);
@@ -258,7 +443,7 @@
 		DeclarationAnnotationAdapter daa1 = new SimpleDeclarationAnnotationAdapter("annot.Foo");
 		DeclarationAnnotationAdapter daa2 = new NestedDeclarationAnnotationAdapter(daa1, "value", "annot.Bar", false);
 		DeclarationAnnotationAdapter daa3 = new NestedDeclarationAnnotationAdapter(daa2, "jimmy", "annot.Baz", false);
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, BooleanLiteral>(daa3, "fred", BooleanStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa3, "fred", BooleanStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 
 		aea.setValue(null);
@@ -287,7 +472,7 @@
 		DeclarationAnnotationAdapter daa1 = new SimpleDeclarationAnnotationAdapter("annot.Foo");
 		DeclarationAnnotationAdapter daa2 = new NestedDeclarationAnnotationAdapter(daa1, "value", "annot.Bar");
 		DeclarationAnnotationAdapter daa3 = new NestedDeclarationAnnotationAdapter(daa2, "jimmy", "annot.Baz");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, BooleanLiteral>(daa3, "fred", BooleanStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa3, "fred", BooleanStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 
 		aea.setValue("true");
@@ -303,7 +488,7 @@
 		DeclarationAnnotationAdapter daa1 = new SimpleDeclarationAnnotationAdapter("annot.Foo");
 		DeclarationAnnotationAdapter daa2 = new NestedDeclarationAnnotationAdapter(daa1, "value", "annot.Bar");
 		DeclarationAnnotationAdapter daa3 = new NestedDeclarationAnnotationAdapter(daa2, "jimmy", "annot.Baz");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, BooleanLiteral>(daa3, "fred", BooleanStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa3, "fred", BooleanStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 
 		aea.setValue("true");
@@ -375,7 +560,7 @@
 		DeclarationAnnotationAdapter daa1 = new SimpleDeclarationAnnotationAdapter("annot.Foo");
 		DeclarationAnnotationAdapter daa2 = new NestedDeclarationAnnotationAdapter(daa1, "value", "annot.Bar");
 		DeclarationAnnotationAdapter daa3 = new NestedIndexedDeclarationAnnotationAdapter(daa2, "jimmy", 2, "annot.Baz");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, NumberLiteral>(daa3, "fred", NumberStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa3, "fred", NumberStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 
 		assertEquals("2", aea.getValue());
@@ -414,7 +599,7 @@
 		this.createAnnotationAndMembers("Foo", "Class bar();");
 		this.createTestType("@annot.Foo(bar=java.lang.Object.class)");
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, TypeLiteral>(daa, "bar", SimpleTypeStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa, "bar", SimpleTypeStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 		assertEquals("java.lang.Object", aea.getValue());
 	}
@@ -423,7 +608,7 @@
 		this.createAnnotationAndMembers("Foo", "Class bar();");
 		this.createTestType();
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, TypeLiteral>(daa, "bar", SimpleTypeStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa, "bar", SimpleTypeStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 		aea.setValue("java.lang.Object");
 		this.assertSourceContains("@Foo(bar=java.lang.Object.class)");
@@ -433,7 +618,7 @@
 		this.createAnnotationAndMembers("Foo", "Class bar();");
 		this.createTestType("@annot.Foo(bar=int.class)");
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, TypeLiteral>(daa, "bar", SimpleTypeStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa, "bar", SimpleTypeStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 		assertNull(aea.getValue());
 	}
@@ -442,7 +627,7 @@
 		this.createAnnotationAndMembers("Foo", "Class bar();");
 		this.createTestType("@annot.Foo(bar=java.util.Map.Entry.class)");
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, TypeLiteral>(daa, "bar", SimpleTypeStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa, "bar", SimpleTypeStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 		assertEquals("java.util.Map.Entry", aea.getValue());
 	}
@@ -451,7 +636,7 @@
 		this.createAnnotationAndMembers("Foo", "Class bar();");
 		this.createTestType("@annot.Foo(bar=int.class)");
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, TypeLiteral>(daa, "bar", PrimitiveTypeStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa, "bar", PrimitiveTypeStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 		assertEquals("int", aea.getValue());
 	}
@@ -460,7 +645,7 @@
 		this.createAnnotationAndMembers("Foo", "Class bar();");
 		this.createTestType();
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, TypeLiteral>(daa, "bar", PrimitiveTypeStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa, "bar", PrimitiveTypeStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 		aea.setValue("int");
 		this.assertSourceContains("@Foo(bar=int.class)");
@@ -470,7 +655,7 @@
 		this.createAnnotationAndMembers("Foo", "Class bar();");
 		this.createTestType("@annot.Foo(bar=java.lang.Object.class)");
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, TypeLiteral>(daa, "bar", PrimitiveTypeStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa, "bar", PrimitiveTypeStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 		assertNull(aea.getValue());
 	}
@@ -479,7 +664,7 @@
 		this.createAnnotationAndMembers("Foo", "Class bar();");
 		this.createTestType("@annot.Foo(bar=void.class)");
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String, TypeLiteral>(daa, "bar", PrimitiveTypeStringExpressionConverter.instance());
+		DeclarationAnnotationElementAdapter<String> daea = new ConversionDeclarationAnnotationElementAdapter<String>(daa, "bar", PrimitiveTypeStringExpressionConverter.instance());
 		AnnotationElementAdapter<String> aea = new MemberAnnotationElementAdapter<String>(this.idField(), daea);
 		assertEquals("void", aea.getValue());
 	}
@@ -555,7 +740,16 @@
 		this.createAnnotationAndMembers("Foo", "String[] bar();");
 		this.createTestType("@annot.Foo(bar={\"string0\", \"string1\"})");
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[], Expression>(daa, "bar", AnnotationStringArrayExpressionConverter.forStringLiterals());
+		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[]>(daa, "bar", AnnotationStringArrayExpressionConverter.forStrings());
+		AnnotationElementAdapter<String[]> aea = new MemberAnnotationElementAdapter<String[]>(this.idField(), daea);
+		assertTrue(Arrays.equals(new String[] {"string0", "string1"}, aea.getValue()));
+	}
+
+	public void testGetValueStringArrayConcatenation() throws Exception {
+		this.createAnnotationAndMembers("Foo", "String[] bar();");
+		this.createTestType("@annot.Foo(bar={\"stri\" + \"ng0\", \"s\" + \"tring1\"})");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[]>(daa, "bar", AnnotationStringArrayExpressionConverter.forStrings());
 		AnnotationElementAdapter<String[]> aea = new MemberAnnotationElementAdapter<String[]>(this.idField(), daea);
 		assertTrue(Arrays.equals(new String[] {"string0", "string1"}, aea.getValue()));
 	}
@@ -564,7 +758,7 @@
 		this.createAnnotationAndMembers("Foo", "String[] bar();");
 		this.createTestType("@annot.Foo(bar={})");
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[], Expression>(daa, "bar", AnnotationStringArrayExpressionConverter.forStringLiterals());
+		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[]>(daa, "bar", AnnotationStringArrayExpressionConverter.forStrings());
 		AnnotationElementAdapter<String[]> aea = new MemberAnnotationElementAdapter<String[]>(this.idField(), daea);
 		assertTrue(Arrays.equals(new String[0], aea.getValue()));
 	}
@@ -573,7 +767,7 @@
 		this.createAnnotationAndMembers("Foo", "String[] bar();");
 		this.createTestType("@annot.Foo(bar=\"string0\")");
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[], Expression>(daa, "bar", AnnotationStringArrayExpressionConverter.forStringLiterals());
+		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[]>(daa, "bar", AnnotationStringArrayExpressionConverter.forStrings());
 		AnnotationElementAdapter<String[]> aea = new MemberAnnotationElementAdapter<String[]>(this.idField(), daea);
 		assertTrue(Arrays.equals(new String[] {"string0"}, aea.getValue()));
 	}
@@ -582,7 +776,7 @@
 		this.createAnnotationAndMembers("Foo", "String[] bar();");
 		this.createTestType("@annot.Foo()");
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[], Expression>(daa, "bar", AnnotationStringArrayExpressionConverter.forStringLiterals());
+		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[]>(daa, "bar", AnnotationStringArrayExpressionConverter.forStrings());
 		AnnotationElementAdapter<String[]> aea = new MemberAnnotationElementAdapter<String[]>(this.idField(), daea);
 		assertTrue(Arrays.equals(new String[0], aea.getValue()));
 	}
@@ -593,7 +787,7 @@
 		this.createTestType();
 		this.assertSourceDoesNotContain(annotation);
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[], Expression>(daa, "bar", AnnotationStringArrayExpressionConverter.forStringLiterals());
+		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[]>(daa, "bar", AnnotationStringArrayExpressionConverter.forStrings());
 		AnnotationElementAdapter<String[]> aea = new MemberAnnotationElementAdapter<String[]>(this.idField(), daea);
 		aea.setValue(new String[] {"string0", "string1"});
 		this.assertSourceContains(annotation);
@@ -605,7 +799,7 @@
 		this.createTestType();
 		this.assertSourceDoesNotContain(annotation);
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[], Expression>(daa, "bar", AnnotationStringArrayExpressionConverter.forStringLiterals());
+		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[]>(daa, "bar", AnnotationStringArrayExpressionConverter.forStrings());
 		AnnotationElementAdapter<String[]> aea = new MemberAnnotationElementAdapter<String[]>(this.idField(), daea);
 		aea.setValue(new String[0]);
 		this.assertSourceDoesNotContain(annotation);
@@ -617,8 +811,8 @@
 		this.createTestType();
 		this.assertSourceDoesNotContain(annotation);
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		ExpressionConverter<String[], Expression> expressionConverter = new AnnotationStringArrayExpressionConverter<StringLiteral>(StringExpressionConverter.instance(), false);
-		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[], Expression>(daa, "bar", expressionConverter);
+		ExpressionConverter<String[]> expressionConverter = new AnnotationStringArrayExpressionConverter(StringExpressionConverter.instance(), false);
+		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[]>(daa, "bar", expressionConverter);
 		AnnotationElementAdapter<String[]> aea = new MemberAnnotationElementAdapter<String[]>(this.idField(), daea);
 		aea.setValue(new String[0]);
 		this.assertSourceContains(annotation);
@@ -630,7 +824,7 @@
 		this.createTestType();
 		this.assertSourceDoesNotContain(annotation);
 		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
-		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[], Expression>(daa, "bar", AnnotationStringArrayExpressionConverter.forStringLiterals());
+		DeclarationAnnotationElementAdapter<String[]> daea = new ConversionDeclarationAnnotationElementAdapter<String[]>(daa, "bar", AnnotationStringArrayExpressionConverter.forStrings());
 		AnnotationElementAdapter<String[]> aea = new MemberAnnotationElementAdapter<String[]>(this.idField(), daea);
 		aea.setValue(new String[] {"string0"});
 		this.assertSourceContains(annotation);
@@ -646,6 +840,16 @@
 		assertTrue(Arrays.equals(new String[] {"enums.TestEnum.XXX", "enums.TestEnum.YYY"}, aea.getValue()));
 	}
 
+	public void testGetValueEnumArrayInvalidEntry() throws Exception {
+		this.createEnum("TestEnum", "XXX, YYY, ZZZ");
+		this.createAnnotationAndMembers("Foo", "enums.TestEnum[] bar();");
+		this.createTestType("@annot.Foo(bar={enums.TestEnum.XXX, 88})");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String[]> daea = new EnumArrayDeclarationAnnotationElementAdapter(daa, "bar");
+		AnnotationElementAdapter<String[]> aea = new MemberAnnotationElementAdapter<String[]>(this.idField(), daea);
+		assertTrue(Arrays.equals(new String[] {"enums.TestEnum.XXX", null}, aea.getValue()));
+	}
+
 	public void testGetValueEnumArrayEmpty() throws Exception {
 		this.createEnum("TestEnum", "XXX, YYY, ZZZ");
 		this.createAnnotationAndMembers("Foo", "enums.TestEnum[] bar();");
@@ -666,6 +870,16 @@
 		assertTrue(Arrays.equals(new String[] {"enums.TestEnum.XXX"}, aea.getValue()));
 	}
 
+	public void testGetValueEnumArraySingleElementInvalid() throws Exception {
+		this.createEnum("TestEnum", "XXX, YYY, ZZZ");
+		this.createAnnotationAndMembers("Foo", "enums.TestEnum[] bar();");
+		this.createTestType("@annot.Foo(bar=\"\")");
+		DeclarationAnnotationAdapter daa = new SimpleDeclarationAnnotationAdapter("annot.Foo");
+		DeclarationAnnotationElementAdapter<String[]> daea = new EnumArrayDeclarationAnnotationElementAdapter(daa, "bar");
+		AnnotationElementAdapter<String[]> aea = new MemberAnnotationElementAdapter<String[]>(this.idField(), daea);
+		assertTrue(Arrays.equals(new String[] {null}, aea.getValue()));
+	}
+
 	public void testGetValueNullEnumArray() throws Exception {
 		this.createEnum("TestEnum", "XXX, YYY, ZZZ");
 		this.createAnnotationAndMembers("Foo", "enums.TestEnum[] bar();");