[337930] - Content assist and validation for JPQL Named Queries.  Includes assist and validation for Java Editor and Java and ORM Details View. Patch from Pascal.
diff --git a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/Pane.java b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/Pane.java
index e1c0863..d3f7ffe 100644
--- a/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/Pane.java
+++ b/common/plugins/org.eclipse.jpt.common.ui/src/org/eclipse/jpt/common/ui/internal/widgets/Pane.java
@@ -149,14 +149,14 @@
 	 * {@link #enableWidgets(boolean)} is called.
 	 */
 	private ArrayList<Control> managedWidgets;
-	
+
 	/**
 	 * The collection of <code>Pane</code>s that are displayed in this pane,
 	 * which will have their enablement state updated when
 	 * {@link #enableWidgets(boolean)} is called.
 	 */
 	private ArrayList<Pane<?>> managedSubPanes;
-	
+
 	/**
 	 * This enabled model is used to store the pane's base enablement state.
 	 * If API is called to set the pane enabled, this model gets updated.  If the pane is thereby
@@ -164,25 +164,25 @@
 	 * enabled.
 	 * @see #getCombinedEnabledModel()
 	 */
-	private final WritablePropertyValueModel<Boolean> baseEnabledModel 
+	private final WritablePropertyValueModel<Boolean> baseEnabledModel
 			= new SimplePropertyValueModel<Boolean>(Boolean.TRUE);
-	
+
 	/**
 	 * This enabled model is used to define the pane's enablement as controlled by other widgets,
 	 * tests, etc. (for example a radio button)
-	 * If this model is changed, and the pane is thereby fully enabled (base enabled model is also 
+	 * If this model is changed, and the pane is thereby fully enabled (base enabled model is also
 	 * in agreement) the pane's widgets are set enabled.
 	 * @see #getCombinedEnabledModel()
 	 */
 	private PropertyValueModel<Boolean> controllerEnabledModel;
-	
+
 	/**
 	 * The "and" combination of {@link #baseEnabledModel} and {@link #controllerEnabledModel}
 	 */
 	private PropertyValueModel<Boolean> combinedEnabledModel;
-	
+
 	private PropertyChangeListener combinedEnabledModelListener;
-	
+
 	/**
 	 * Creates a new <code>Pane</code>.
 	 *
@@ -194,7 +194,7 @@
 	protected Pane(
 			Pane<? extends T> parentPane,
 	        Composite parent) {
-		
+
 		this(parentPane, parent, true);
 	}
 
@@ -214,7 +214,7 @@
 			Pane<? extends T> parentPane,
 	        Composite parent,
 	        boolean automaticallyAlignWidgets) {
-		
+
 		this(
 			parentPane,
 			parentPane.getSubjectHolder(),
@@ -239,7 +239,7 @@
 	        Composite parent,
 	        boolean automaticallyAlignWidgets,
 	        boolean parentManagePane) {
-		
+
 		this(
 			parentPane,
 			parentPane.getSubjectHolder(),
@@ -261,16 +261,16 @@
 			Pane<?> parentPane,
 	        PropertyValueModel<? extends T> subjectHolder,
 	        Composite parent) {
-		
+
 		this(parentPane, subjectHolder, parent, true);
 	}
-	
+
 	protected Pane(
 			Pane<?> parentPane,
 	        PropertyValueModel<? extends T> subjectHolder,
 	        Composite parent,
 	        PropertyValueModel<Boolean> enabledModel) {
-		
+
 		this(parentPane, subjectHolder, parent, true, enabledModel);
 	}
 
@@ -292,20 +292,20 @@
 			PropertyValueModel<? extends T> subjectHolder,
 			Composite parent,
 			boolean automaticallyAlignWidgets) {
-		
+
 		this(parentPane, subjectHolder, parent, automaticallyAlignWidgets, true);
 	}
-	
+
 	protected Pane(
 			Pane<?> parentPane,
 			PropertyValueModel<? extends T> subjectHolder,
 			Composite parent,
 			boolean automaticallyAlignWidgets,
 			PropertyValueModel<Boolean> enabledModel) {
-		
+
 		this(parentPane, subjectHolder, parent, automaticallyAlignWidgets, true, enabledModel);
 	}
-	
+
 	/**
 	 * Creates a new <code>Pane</code>.
 	 *
@@ -325,26 +325,26 @@
 			Pane<?> parentPane,
 			PropertyValueModel<? extends T> subjectHolder,
 			Composite parent,
-			boolean automaticallyAlignWidgets, 
+			boolean automaticallyAlignWidgets,
 			boolean parentManagePane) {
-		
+
 		this(subjectHolder, parent, parentPane.getWidgetFactory());
 		this.initialize(parentPane, automaticallyAlignWidgets, parentManagePane);
 	}
-	
+
 	protected Pane(
 			Pane<?> parentPane,
 			PropertyValueModel<? extends T> subjectHolder,
 			Composite parent,
-			boolean automaticallyAlignWidgets, 
+			boolean automaticallyAlignWidgets,
 			boolean parentManagePane,
 			PropertyValueModel<Boolean> enabledModel) {
-		
+
 		this(subjectHolder, parent, parentPane.getWidgetFactory());
 		this.initialize(parentPane, automaticallyAlignWidgets, parentManagePane);
 		this.initializeEnabledModel(enabledModel);
 	}
-	
+
 	/**
 	 * Creates a new <code>Pane</code>.
 	 *
@@ -358,7 +358,7 @@
 			PropertyValueModel<? extends T> subjectHolder,
 			Composite parent,
 			WidgetFactory widgetFactory) {
-		
+
 		super();
 		this.initialize(subjectHolder, widgetFactory);
 		this.container = this.addContainer(parent);
@@ -375,7 +375,7 @@
 	private void initialize(
 			PropertyValueModel<? extends T> subjectHolder,
 	        WidgetFactory widgetFactory) {
-		
+
 		Assert.isNotNull(subjectHolder, "The subject holder cannot be null");
 
 		this.subjectHolder         = (PropertyValueModel<T>) subjectHolder;
@@ -387,7 +387,7 @@
 		this.rightControlAligner   = new ControlAligner();
 		this.subjectChangeListener = this.buildSubjectChangeListener();
 		this.aspectChangeListener  = this.buildAspectChangeListener();
-		
+
 		this.initialize();
 	}
 
@@ -411,16 +411,16 @@
 			Pane<?> parentPane,
 			boolean automaticallyAlignWidgets,
 	        boolean parentManagePane) {
-		
+
 		// Register this pane with the parent pane, it will call the methods
 		// automatically (engageListeners(), disengageListeners(), populate(),
 		// dispose(), etc)
 		parentPane.registerSubPane(this);
-		
+
 		if (parentManagePane) {
 			parentPane.manageSubPane(this);
 		}
-		
+
 		// Align the left and right controls with the controls from the parent
 		// pane
 		if (automaticallyAlignWidgets) {
@@ -428,21 +428,21 @@
 			parentPane.addAlignRight(this);
 		}
 	}
-	
+
 	private void initializeEnabledModel(PropertyValueModel<Boolean> enabledModel) {
 		this.controllerEnabledModel = enabledModel;
-		this.combinedEnabledModel = 
+		this.combinedEnabledModel =
 				CompositeBooleanPropertyValueModel.and(this.baseEnabledModel, this.controllerEnabledModel);
 		this.combinedEnabledModelListener = buildCombinedEnabledModelListener();
 		this.combinedEnabledModel.addPropertyChangeListener(
 				PropertyValueModel.VALUE, this.combinedEnabledModelListener);
 		enableWidgets_(getCombinedEnablement());
 	}
-	
+
 	private PropertyChangeListener buildCombinedEnabledModelListener() {
 		return new SWTPropertyChangeListenerWrapper(buildControllerEnabledModelListener_());
 	}
-	
+
 	private PropertyChangeListener buildControllerEnabledModelListener_() {
 		return new PropertyChangeListener() {
 			@SuppressWarnings("unchecked")
@@ -451,7 +451,7 @@
 			}
 		};
 	}
-	
+
 	/**
 	 * Initializes the layout of this pane.
 	 *
@@ -467,7 +467,7 @@
 		}
 		this.managedWidgets.add(control);
 	}
-	
+
 	private void manageSubPane(Pane<?> subPane) {
 		if (this.managedSubPanes.contains(subPane)) {
 			throw new IllegalStateException();
@@ -585,10 +585,10 @@
 
 		return this.addButton(container, text, null, buttonAction);
 	}
-	
+
 	/**
-	 * Creates a new unmanaged <code>Button</code> widget.  Unmanaged means 
-	 * that this Pane will not handle the enabling/disabling of this widget.  
+	 * Creates a new unmanaged <code>Button</code> widget.  Unmanaged means
+	 * that this Pane will not handle the enabling/disabling of this widget.
 	 * The owning object will handle it with its own PaneEnabler or ControlEnabler.
 	 *
 	 * @param parent The parent container
@@ -626,10 +626,10 @@
 
 		return button;
 	}
-	
+
 	/**
-	 * Creates a new unmanaged <code>Button</code> widget.  Unmanaged means 
-	 * that this Pane will not handle the enabling/disabling of this widget.  
+	 * Creates a new unmanaged <code>Button</code> widget.  Unmanaged means
+	 * that this Pane will not handle the enabling/disabling of this widget.
 	 * The owning object will handle it with its own PaneEnabler or ControlEnabler.
 	 *
 	 * @param parent The parent container
@@ -697,7 +697,7 @@
 	        String buttonText,
 	        WritablePropertyValueModel<Boolean> booleanHolder,
 	        String helpId) {
-		
+
 		return this.addToggleButton(
 			parent,
 			buttonText,
@@ -705,19 +705,19 @@
 			helpId,
 			SWT.CHECK);
 	}
-	
+
 	protected final Button addCheckBox(
 			Composite parent,
 			String buttonText,
 			WritablePropertyValueModel<Boolean> booleanHolder,
 			String helpId,
 			PropertyValueModel<Boolean> enabledModel) {
-		
+
 		Button button = this.addUnmanagedToggleButton(parent, buttonText, booleanHolder, helpId, SWT.CHECK);
 		this.controlEnabledState(enabledModel, button);
 		return button;
 	}
-	
+
 	/**
 	 * Creates a new <code>Section</code> that can be collapsed. A sub-pane is
 	 * automatically added as its client and is the returned <code>Composite</code>.
@@ -731,13 +731,13 @@
 	protected final Composite addCollapsibleSection(
 			Composite container,
 	        String sectionText) {
-		
+
 		return this.addCollapsibleSection(
 				container,
 				sectionText,
 				new SimplePropertyValueModel<Boolean>(Boolean.FALSE));
 	}
-	
+
 	/**
 	 * Creates a new <code>Section</code> that can be collapsed. A sub-pane is
 	 * automatically added as its client and is the returned <code>Composite</code>.
@@ -778,10 +778,10 @@
 	                                          String sectionText,
 	                                          int type,
 	                                          PropertyValueModel<Boolean> expandedStateHolder) {
-		
+
 		return addCollapsibleSection(container, sectionText, null, type, expandedStateHolder);
 	}
-	
+
 	/**
 	 * Creates a new <code>Section</code>. A sub-pane is automatically added as
 	 * its client and is the returned <code>Composite</code>.
@@ -847,7 +847,7 @@
 			expandedStateHolder
 		);
 	}
-	
+
 	/**
 	 * Creates a new <code>Section</code>. A sub-pane is automatically added as
 	 * its client and is the returned <code>Composite</code>.
@@ -991,7 +991,7 @@
 			WritablePropertyValueModel<V> selectedItemHolder,
 			StringConverter<V> stringConverter,
 			PropertyValueModel<Boolean> enabledModel) {
-		
+
 		Combo combo = this.addUnmanagedCombo(container, listHolder, selectedItemHolder, stringConverter);
 		this.controlEnabledState(enabledModel, combo);
 		return combo;
@@ -1029,28 +1029,28 @@
 	protected Composite addContainer(Composite parent) {
 		return this.addSubPane(parent);
 	}
-	
+
 	protected final <V> Combo addEditableCombo(
 			Composite container,
 			ListValueModel<V> listHolder,
 			WritablePropertyValueModel<V> selectedItemHolder,
 			StringConverter<V> stringConverter,
 			PropertyValueModel<Boolean> enabledModel) {
-		
+
 		Combo combo = this.addUnmanagedEditableCombo(container, listHolder, selectedItemHolder, stringConverter);
 		this.controlEnabledState(enabledModel, combo);
 		return combo;
 	}
-	
+
 	protected final Combo addEditableCombo(
 			Composite container) {
-		
+
 		Combo combo = this.widgetFactory.createEditableCombo(container);
 		combo.setLayoutData(getFieldGridData());
 		this.manageWidget(combo);
 		return combo;
 	}
-	
+
 	/**
 	 * Creates a new editable <code>Combo</code>.
 	 *
@@ -1159,7 +1159,7 @@
 	 */
 	protected final Label addLabel(Composite container,
 	                                 String labelText) {
-		
+
 		Label label = addUnmanagedLabel(container, labelText);
 		manageWidget(label);
 		return label;
@@ -1176,8 +1176,8 @@
 	}
 
 	/**
-	 * Creates a new unmanaged <code>Label</code> widget.  Unmanaged means 
-	 * that this Pane will not handle the enabling/disabling of this widget.  
+	 * Creates a new unmanaged <code>Label</code> widget.  Unmanaged means
+	 * that this Pane will not handle the enabling/disabling of this widget.
 	 * The owning object will handle it with its own PaneEnabler or ControlEnabler.
 	 *
 	 * @param parent The parent container
@@ -1201,7 +1201,7 @@
 	 * @param selectedItemHolder The holder of the selected item
 	 * @param rightControl The control shown to the right of the main widget
 	 * @param helpId The topic help ID to be registered for the given center
-	 * compositer
+	 * composite
 	 * @return The container of the label and the given center control
 	 *
 	 * @category Layout
@@ -1241,7 +1241,7 @@
 	 * @param listHolder The <code>ListValueHolder</code>
 	 * @param selectedItemHolder The holder of the selected item
 	 * @param helpId The topic help ID to be registered for the given center
-	 * compositer
+	 * composite
 	 * @return The container of the label and the given center control
 	 *
 	 * @category Layout
@@ -1273,7 +1273,7 @@
 	 * @param centerControl The main widget
 	 * @param rightControl The control shown to the right of the main widget
 	 * @param helpId The topic help ID to be registered for the given center
-	 * compositer
+	 * composite
 	 * @return The container of the label and the given center control
 	 *
 	 * @category Layout
@@ -1330,7 +1330,7 @@
 
 		return container;
 	}
-	
+
 	/**
 	 * Creates a new container that will have the given center control labeled
 	 * with the given label.
@@ -1366,7 +1366,7 @@
 	 * @param labelText The text to label the main composite
 	 * @param centerPane The main widget
 	 * @param helpId The topic help ID to be registered for the given center
-	 * compositer
+	 * composite
 	 * @return The container of the label and the given center control
 	 *
 	 * @category Layout
@@ -1418,7 +1418,7 @@
 	 * @param centerControl The main widget
 	 * @param rightControl The control shown to the right of the main widget
 	 * @param helpId The topic help ID to be registered for the given center
-	 * compositer
+	 * composite
 	 * @return The container of the label and the given center control
 	 *
 	 * @category Layout
@@ -1446,7 +1446,7 @@
 	 * @param labelText The text to label the main composite
 	 * @param centerControl The main widget
 	 * @param helpId The topic help ID to be registered for the given center
-	 * compositer
+	 * composite
 	 * @return The container of the label and the given center control
 	 *
 	 * @category Layout
@@ -1475,7 +1475,7 @@
 	 * @param centerControl The main widget
 	 * @param rightControl The control shown to the right of the main widget
 	 * @param helpId The topic help ID to be registered for the given center
-	 * compositer
+	 * composite
 	 * @return The newly created <code>CCombo</code>
 	 *
 	 * @category Layout
@@ -1509,7 +1509,7 @@
 	 * @param comboListener The listener that will be notified when the selection
 	 * changes
 	 * @param helpId The topic help ID to be registered for the given center
-	 * compositer
+	 * composite
 	 * @return The newly created <code>CCombo</code>
 	 *
 	 * @category Layout
@@ -1539,7 +1539,7 @@
 	 * into human readable strings
 	 * @param rightControl The control shown to the right of the main widget
 	 * @param helpId The topic help ID to be registered for the given center
-	 * compositer
+	 * composite
 	 * @return The newly created <code>CCombo</code>
 	 *
 	 * @category Layout
@@ -1581,7 +1581,7 @@
 	 * @param labelProvider The provider responsible to convert the combo's items
 	 * into human readable strings
 	 * @param helpId The topic help ID to be registered for the given center
-	 * compositer
+	 * composite
 	 * @return The newly created <code>CCombo</code>
 	 *
 	 * @category Layout
@@ -1601,7 +1601,7 @@
 			helpId
 		);
 	}
-	
+
 	/**
 	 * Creates a new container that will have an editable combo labeled with the
 	 * given text.
@@ -1645,7 +1645,7 @@
 	 * into a string representation
 	 * @param rightControl The control shown to the right of the main widget
 	 * @param helpId The topic help ID to be registered for the given center
-	 * compositer
+	 * composite
 	 * @return The newly created <code>Combo</code>
 	 *
 	 * @category Layout
@@ -1687,7 +1687,7 @@
 	 * @param stringConverter The converter responsible to transform each item
 	 * into a string representation
 	 * @param helpId The topic help ID to be registered for the given center
-	 * compositer
+	 * composite
 	 * @return The newly created <code>Combo</code>
 	 *
 	 * @category Layout
@@ -1884,7 +1884,7 @@
 
 	/**
 	 * Creates a new managed spinner. Managed means that this Pane will
-	 * handle enabling/disabling of this widget if a PaneEnabler is used.  
+	 * handle enabling/disabling of this widget if a PaneEnabler is used.
 	 *
 	 * @param parent The parent container
 	 * @param numberHolder The holder of the integer value
@@ -1945,10 +1945,10 @@
 
 		return spinner;
 	}
-	
+
 	/**
 	 * Creates a new managed DateTime of type SWT.TIME.  Managed means that this Pane will
-	 * handle enabling/disabling of this widget if a PaneEnabler is used.  
+	 * handle enabling/disabling of this widget if a PaneEnabler is used.
 	 *
 	 * @param parent The parent container
 	 * @param hoursHolder The holder of the hours integer value
@@ -1964,7 +1964,7 @@
 											WritablePropertyValueModel<Integer> minutesHolder,
 											WritablePropertyValueModel<Integer> secondsHolder,
 											String helpId) {
-		
+
 		DateTime dateTime = this.addUnmanagedDateTime(parent, hoursHolder, minutesHolder, secondsHolder, helpId);
 		this.manageWidget(dateTime);
 
@@ -2003,11 +2003,11 @@
 											WritablePropertyValueModel<Integer> minutesHolder,
 											WritablePropertyValueModel<Integer> secondsHolder,
 											String helpId) {
-		
+
 		DateTime dateTime = this.widgetFactory.createDateTime(parent, SWT.TIME);
-		
+
 		DateTimeModelAdapter.adapt(hoursHolder, minutesHolder, secondsHolder, dateTime);
-	
+
 		if (helpId != null) {
 			getHelpSystem().setHelp(dateTime, helpId);
 		}
@@ -2043,7 +2043,7 @@
 		return combo;
 	}
 
-	
+
 	/**
 	 * Creates a new editable <code>Combo</code>.
 	 *
@@ -2109,7 +2109,7 @@
 		return text;
 	}
 	/**
-	 * 
+	 *
 	 * Creates a new container that will have a text field as the center control
 	 * labeled with the given label.
 	 *
@@ -2233,12 +2233,12 @@
 
 		return list;
 	}
-	
+
 	/**
 	 * Creates a new unmanaged list and notify the given selection holder when the
 	 * selection changes. If the selection count is different than one than the
-	 * holder will receive <code>null</code>. 
-	 * Unmanaged means that this Pane will not handle the enabling/disabling of this widget.  
+	 * holder will receive <code>null</code>.
+	 * Unmanaged means that this Pane will not handle the enabling/disabling of this widget.
 	 * The owning object will handle it with its own PaneEnabler or ControlEnabler.
 	 *
 	 * @param container The parent container
@@ -2298,7 +2298,7 @@
 
 		return text;
 	}
-	
+
 	/**
 	 * Creates a new <code>Text</code> widget that has multiple lines.
 	 *
@@ -2310,14 +2310,11 @@
 	 * @category Layout
 	 */
 	protected final Text addMultiLineText(Composite container,
-	                                        int lineCount,
-	                                        String helpId) {
+	                                      int lineCount,
+	                                      String helpId) {
 
 		Text text = this.addMultiLineText(container);
-		
-		GridData gridData   = getFieldGridData();
-		gridData.heightHint = text.getLineHeight() * lineCount;
-		text.setLayoutData(gridData);
+		adjustMultiLineTextLayout(container, lineCount, text, text.getLineHeight());
 
 		if (helpId != null) {
 			getHelpSystem().setHelp(text, helpId);
@@ -2364,6 +2361,33 @@
 	}
 
 	/**
+	 * Adjusts the layout of the given container so that the text control has the correct amount of
+	 * lines by default.
+	 */
+	protected final void adjustMultiLineTextLayout(Composite container,
+	                                               int lineCount,
+	                                               Control text,
+	                                               int lineHeight) {
+
+		int textHeight = text.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
+
+		// Specify the number of lines the text area should display
+		GridData gridData = (GridData) text.getLayoutData();
+		if (gridData == null) {
+			gridData = this.getFieldGridData();
+			text.setLayoutData(gridData);
+		}
+		gridData.heightHint = lineHeight * lineCount;
+
+		// Move the label to the top of its cell
+		Control label = container.getChildren()[0];
+		int labelHeight = label.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
+
+		gridData = (GridData) label.getLayoutData();
+		gridData.verticalAlignment = SWT.TOP;
+		gridData.verticalIndent   += (Math.abs(textHeight - labelHeight) / 2);
+	}
+	/**
 	 * Creates a new <code>PageBook</code> and set the proper layout and layout
 	 * data.
 	 *
@@ -2425,7 +2449,7 @@
 
 		return text;
 	}
-	
+
 	/**
 	 * Creates a new <code>Text</code> widget.
 	 *
@@ -2608,7 +2632,7 @@
 		section.setText(sectionText);
 		section.marginWidth  = 0;
 		section.marginHeight = 0;
-		
+
 		if (description != null) {
 			section.setDescription(description);
 		}
@@ -2869,7 +2893,7 @@
 			helpId
 		);
 	}
-	
+
 	/**
 	 * Creates a new unmanaged table.  Unmanaged means that this Pane will
 	 * not handle the enabling/disabling of this widget.  The owning object will handle
@@ -2904,10 +2928,10 @@
 		this.manageWidget(text);
 		return text;
 	}
-	
+
 	/**
-	 * Creates a new unmanaged <code>Text</code> widget.  Unmanaged means 
-	 * that this Pane will not handle the enabling/disabling of this widget.  
+	 * Creates a new unmanaged <code>Text</code> widget.  Unmanaged means
+	 * that this Pane will not handle the enabling/disabling of this widget.
 	 * The owning object will handle it with its own PaneEnabler or ControlEnabler.
 	 *
 	 * @param container The parent container
@@ -2940,10 +2964,10 @@
 
 		return text;
 	}
-	
+
 	/**
-	 * Creates a new unmanaged <code>Text</code> widget.  Unmanaged means 
-	 * that this Pane will not handle the enabling/disabling of this widget.  
+	 * Creates a new unmanaged <code>Text</code> widget.  Unmanaged means
+	 * that this Pane will not handle the enabling/disabling of this widget.
 	 * The owning object will handle it with its own PaneEnabler or ControlEnabler.
 	 *
 	 * @param container The parent container
@@ -2959,10 +2983,10 @@
 		if (helpId != null) {
 			getHelpSystem().setHelp(text, helpId);
 		}
-		
+
 		return text;
 	}
-	
+
 	/**
 	 * Creates a new <code>Text</code> widget.
 	 *
@@ -2997,7 +3021,7 @@
 
 		return text;
 	}
-	
+
 	protected final Text addText(
 			Composite container,
 			WritablePropertyValueModel<String> textHolder,
@@ -3010,8 +3034,8 @@
 	}
 
 	/**
-	 * Creates a new unmanaged <code>Text</code> widget.  Unmanaged means 
-	 * that this Pane will not handle the enabling/disabling of this widget.  
+	 * Creates a new unmanaged <code>Text</code> widget.  Unmanaged means
+	 * that this Pane will not handle the enabling/disabling of this widget.
 	 * The owning object will handle it with its own PaneEnabler or ControlEnabler.
 	 *
 	 * @param container The parent container
@@ -3060,7 +3084,7 @@
 
 		return addTitledGroup(container, title, 1, helpId);
 	}
-	
+
 	/**
 	 * Creates a new container with a titled border.
 	 *
@@ -3077,7 +3101,7 @@
 	                                      String helpId) {
 
 		Group group = this.widgetFactory.createGroup(container, title);
-		//manageWidget(group); TODO unsure if I want to manage groups, 
+		//manageWidget(group); TODO unsure if I want to manage groups,
 		//also should probably rename this addUnmanagedTitledPane
 		group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
 
@@ -3098,9 +3122,9 @@
 	}
 
 	/**
-	 * Creates a new unmanaged new toggle button (radio button or check box).  
-	 * Unmanaged means  that this Pane will not handle the enabling/disabling 
-	 * of this widget. The owning object will handle it with its own PaneEnabler 
+	 * Creates a new unmanaged new toggle button (radio button or check box).
+	 * Unmanaged means  that this Pane will not handle the enabling/disabling
+	 * of this widget. The owning object will handle it with its own PaneEnabler
 	 * or ControlEnabler.
 	 *
 	 * @param parent The parent container
@@ -3117,9 +3141,9 @@
 	        WritablePropertyValueModel<Boolean> booleanHolder,
 	        String helpId,
 	        int toggleButtonType) {
-		
+
 		Button button;
-		
+
 		if (toggleButtonType == SWT.PUSH) {
 			button = this.widgetFactory.createPushButton(parent, buttonText);
 		}
@@ -3132,17 +3156,17 @@
 		else {
 			button = this.widgetFactory.createButton(parent, buttonText);
 		}
-		
+
 		button.setLayoutData(new GridData());
 		SWTTools.bind(booleanHolder, button);
-		
+
 		if (helpId != null) {
 			getHelpSystem().setHelp(button, helpId);
 		}
-		
+
 		return button;
 	}
-	
+
 	/**
 	 * Creates a new toggle button (radio button or check box) using the given
 	 * information.
@@ -3161,12 +3185,12 @@
 	        WritablePropertyValueModel<Boolean> booleanHolder,
 	        String helpId,
 	        int toggleButtonType) {
-		
+
 		Button button = addUnmanagedToggleButton(
-				parent, 
-				buttonText, 
-				booleanHolder, 
-				helpId, 
+				parent,
+				buttonText,
+				booleanHolder,
+				helpId,
 				toggleButtonType);
 		this.manageWidget(button);
 		return button;
@@ -3254,7 +3278,7 @@
 	protected void doPopulate() {
 		this.log(Tracing.UI_LAYOUT, "   ->doPopulate()");
 	}
-	
+
 	private void controlEnabledState(PropertyValueModel<Boolean> booleanModel, Control... controls) {
 		this.controlEnabledState_(this.wrapEnabledModel(booleanModel), controls);
 	}
@@ -3266,28 +3290,28 @@
 	private PropertyValueModel<Boolean> wrapEnabledModel(PropertyValueModel<Boolean> booleanModel) {
 		return new TransformationPropertyValueModel<Boolean, Boolean>(booleanModel, NonNullBooleanTransformer.FALSE);
 	}
-	
+
 	private void controlEnabledState_(PropertyValueModel<Boolean> booleanModel, Control... controls) {
 		SWTTools.controlEnabledState(this.andEnabledModel(booleanModel), controls);
 	}
-	
+
 	private PropertyValueModel<Boolean> getCombinedEnabledModel() {
 		return (this.combinedEnabledModel != null) ? this.combinedEnabledModel : this.baseEnabledModel;
 	}
-	
+
 	private boolean getCombinedEnablement() {
 		Boolean enabled = getCombinedEnabledModel().getValue();
 		return (enabled == null) ? true : enabled.booleanValue();
 	}
-	
+
 	private PropertyValueModel<Boolean> andEnabledModel(PropertyValueModel<Boolean> booleanModel) {
 		return CompositeBooleanPropertyValueModel.and(getCombinedEnabledModel(), booleanModel);
 	}
-	
+
 	protected void controllerEnablementChanged() {
 		enableWidgets_(getCombinedEnablement());
 	}
-	
+
 	/**
 	 * Changes the enablement state of the widgets of this pane.
 	 *
@@ -3300,23 +3324,23 @@
 		this.baseEnabledModel.setValue(Boolean.valueOf(enabled));
 		enableWidgets_(getCombinedEnablement());
 	}
-	
+
 	private void enableWidgets_(boolean enabled) {
 		if (! this.container.isDisposed()) {
 			for (Control control : this.managedWidgets) {
 				control.setEnabled(enabled);
 			}
-			
+
 			for (Pane<?> subPane : this.managedSubPanes) {
 				subPane.enableWidgets(enabled);
 			}
 		}
 	}
-	
+
 	private void engageSubjectHolder() {
 		this.subjectHolder.addPropertyChangeListener(PropertyValueModel.VALUE, this.subjectChangeListener);
 	}
-	
+
 	/**
 	 * engage the specified subject
 	 */
@@ -3698,18 +3722,18 @@
 			}
 		}
 	}
-	
+
 	public void dispose() {
 		this.log(Tracing.UI_LAYOUT, "dispose()");
 
 		// Dispose this pane
 		this.disengageListeners(getSubject());
 		this.disengageSubjectHolder();
-		
+
 		if (this.combinedEnabledModel != null && this.combinedEnabledModelListener != null) {
 			this.combinedEnabledModel.removePropertyChangeListener(PropertyValueModel.VALUE, this.combinedEnabledModelListener);
 		}
-		
+
 		this.leftControlAligner.dispose();
 		this.rightControlAligner.dispose();
 
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/META-INF/MANIFEST.MF b/jpa/plugins/org.eclipse.jpt.jpa.core/META-INF/MANIFEST.MF
index 9cdc8de..44bfae4 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/META-INF/MANIFEST.MF
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/META-INF/MANIFEST.MF
@@ -25,6 +25,7 @@
  org.eclipse.jst.common.project.facet.core;bundle-version="[1.3.100,2.0.0)",
  org.eclipse.jst.j2ee;bundle-version="[1.1.200,2.0.0)",
  org.eclipse.jst.j2ee.core;bundle-version="[1.1.200,2.0.0)",
+ org.eclipse.persistence.jpa.jpql;bundle-version="[1.0.0, 2.0.0)",
  org.eclipse.wst.common.emf;bundle-version="[1.1.200,2.0.0)",
  org.eclipse.wst.common.emfworkbench.integration;bundle-version="[1.1.200,2.0.0)",
  org.eclipse.wst.common.frameworks;bundle-version="[1.1.200,2.0.0)",
@@ -62,6 +63,7 @@
  org.eclipse.jpt.jpa.core.internal.jpa2.resource.java;x-internal:=true,
  org.eclipse.jpt.jpa.core.internal.jpa2.resource.java.binary;x-internal:=true,
  org.eclipse.jpt.jpa.core.internal.jpa2.resource.java.source;x-internal:=true,
+ org.eclipse.jpt.jpa.core.internal.jpql;x-friends:="org.eclipse.jpt.jpa.ui",
  org.eclipse.jpt.jpa.core.internal.libprov;x-internal:=true,
  org.eclipse.jpt.jpa.core.internal.libval;x-internal:=true,
  org.eclipse.jpt.jpa.core.internal.operations;x-internal:=true,
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/property_files/jpa_jpql_validation.properties b/jpa/plugins/org.eclipse.jpt.jpa.core/property_files/jpa_jpql_validation.properties
new file mode 100644
index 0000000..2fc5290
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/property_files/jpa_jpql_validation.properties
@@ -0,0 +1,484 @@
+################################################################################
+# Copyright (c) 2011 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.
+# 
+# Contributors:
+#     Oracle - initial API and implementation
+################################################################################
+
+# AbsExpression - Grammar
+ABS_EXPRESSION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+ABS_EXPRESSION_MISSING_EXPRESSION = The encapsulated expression must be provided for an ABS expression.
+ABS_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the ABS expression.
+ABS_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the ABS expression.
+# AbsExpression - Semantic
+ABS_EXPRESSION_INVALID_NUMERIC_EXPRESSION = The encapsulated expression is not a valid numeric expression.
+
+# AbstractFromClause - Grammar
+ABSTRACT_FROM_CLAUSE_IDENTIFICATION_VARIABLE_DECLARATION_ENDS_WITH_COMMA = The FROM clause cannot end with a comma.
+ABSTRACT_FROM_CLAUSE_IDENTIFICATION_VARIABLE_DECLARATION_IS_MISSING_COMMA = The FROM clause has ''{0}'' and ''{1}'' that are not separated by a comma.
+ABSTRACT_FROM_CLAUSE_MISSING_IDENTIFICATION_VARIABLE_DECLARATION = The FROM clause must defined at least one identification variable declaration.
+ABSTRACT_FROM_CLAUSE_WRONG_ORDER_OF_IDENTIFICATION_VARIABLE_DECLARATION = The identification variable ''{0}'' is declared after its usage. Identification variables are evaluated from left to right.
+
+# AbstractPathExpression - Grammar
+ABSTRACT_PATH_EXPRESSION_CANNOT_END_WITH_COMMA = A path expression cannot end with a comma.
+ABSTRACT_PATH_EXPRESSION_MISSING_IDENTIFICATION_VARIABLE = A path expression must start with an identification variable.
+
+# AbstractSchemaName - Grammar
+ABSTRACT_SCHEMA_NAME_INVALID = The abstract schema type ''{0}'' is unknown.
+ABSTRACT_SCHEMA_NAME_NOT_RESOLVABLE = ''{0}'' cannot be resolved to a type.
+# AbstractSchemaName - Semantic
+PATH_EXPRESSION_NOT_RELATIONSHIP_MAPPING = The derived path ''{0}'' does not represent an association field.
+
+# AbstractSelectClause - Grammar
+ABSTRACT_SELECT_CLAUSE_SELECT_EXPRESSION_ENDS_WITH_COMMA = The select expression cannot end with a comma.
+ABSTRACT_SELECT_CLAUSE_SELECT_EXPRESSION_IS_MISSING_COMMA = The SELECT clause has ''{0}'' and ''{1}'' that are not separated by a comma.
+ABSTRACT_SELECT_CLAUSE_SELECT_EXPRESSION_MALFORMED = The select expression is malformed.
+ABSTRACT_SELECT_CLAUSE_SELECT_MISSING_EXPRESSION = The select expression is missing from the SELECT clause.
+
+# AbstractSelectStatement - Grammar
+ABSTRACT_SELECT_STATEMENT_FROM_CLAUSE_MSSING = A select statement must have a FROM clause.
+
+# AdditionExpression - Semantic
+ADDITION_EXPRESSION_LEFT_EXPRESSION_WRONG_TYPE = The left side of the addition is not a valid arithmetic expression.
+ADDITION_EXPRESSION_RIGHT_EXPRESSION_WRONG_TYPE = The right side of the addition is not a valid arithmetic expression.
+
+# AllOrAnyExpression - Grammar
+ALL_OR_ANY_EXPRESSION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+ALL_OR_ANY_EXPRESSION_MISSING_EXPRESSION = The subquery must be provided for an {0} expression.
+ALL_OR_ANY_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the {0} expression.
+ALL_OR_ANY_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the {0} expression.
+ALL_OR_ANY_EXPRESSION_NOT_PART_OF_COMPARISON_EXPRESSION = The {0} expression must be part of a comparison expression.
+
+# ArithmeticFactor - Grammar
+ARITHMETIC_FACTOR_MISSING_EXPRESSION = An arithmetic factor must be followed by an expression.
+# ArithmeticFactor - Semantic
+ARITHMETIC_FACTOR_INVALID_EXPRESSION = The expression must be an arithmetic expression.
+
+# ArithmeticExpression - Grammar
+ARITHMETIC_EXPRESSION_INVALID_LEFT_EXPRESSION = The left expression is not an arithmetic expression.
+ARITHMETIC_EXPRESSION_INVALID_RIGHT_EXPRESSION = The right expression is not an arithmetic expression.
+ARITHMETIC_EXPRESSION_MISSING_LEFT_EXPRESSION = The left expression is missing from the arithmetic expression.
+ARITHMETIC_EXPRESSION_MISSING_RIGHT_EXPRESSION = The right expression is missing from the arithmetic expression.
+
+# AvgFunction - Grammar
+AVG_FUNCTION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+AVG_FUNCTION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the AVG expression.
+AVG_FUNCTION_MISSING_EXPRESSION = The encapsulated expression must be provided for an AVG expression.
+AVG_FUNCTION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the AVG expression.
+# AvgFunction - Semantic
+AVG_FUNCTION_INVALID_NUMERIC_EXPRESSION = The encapsulated expression is not a valid numeric expression.
+
+# BetweenExpression - Grammar
+BETWEEN_EXPRESSION_MISSING_EXPRESSION = The result expression is missing from the BETWEEN expression.
+BETWEEN_EXPRESSION_MISSING_LOWER_BOUND_EXPRESSION = The lower bound expression is missing from the BETWEEN expression.
+BETWEEN_EXPRESSION_MISSING_AND = The identifier AND is missing from the BETWEEN expression.
+BETWEEN_EXPRESSION_MISSING_UPPER_BOUND_EXPRESSION = The upper bound expression is missing from the BETWEEN expression.
+# BetweenExpression - Semantic
+BETWEEN_EXPRESSION_WRONG_TYPE = The expression's type and the lower and upper bound expressions' type have to be the same type.
+
+# CaseExpression - Grammar
+CASE_EXPRESSION_MISSING_ELSE_EXPRESSION = A CASE expression must have an ELSE expression.
+CASE_EXPRESSION_MISSING_ELSE_IDENTIFIER = The identifier ELSE is missing from the CASE expression.
+CASE_EXPRESSION_MISSING_END_IDENTIFIER = The identifier END is missing from the CASE expression.
+CASE_EXPRESSION_MISSING_WHEN_CLAUSE = A CASE expression must define at least one WHEN clause.
+CASE_EXPRESSION_WHEN_CLAUSES_END_WITH_COMMA = The WHEN clauses cannot end with a comma.
+CASE_EXPRESSION_WHEN_CLAUSES_HAS_COMMA = Two WHEN clauses cannot be separated by a comma.
+
+# CoalesceExpression - Grammar
+COALESCE_EXPRESSION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+COALESCE_EXPRESSION_MISSING_EXPRESSION = The encapsulated expressions must be provided for a COALESCE expression.
+COALESCE_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the COALESCE expression.
+COALESCE_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the COALESCE expression.
+
+# CollectionExpression - Grammar
+COLLECTION_EXPRESSION_MISSING_EXPRESSION = An expression at position {0} must be defined.
+
+# CollectionMemberExpression - Grammar
+COLLECTION_MEMBER_EXPRESSION_MISSING_ENTITY_EXPRESSION = A collection member expression must define an entity expression.
+COLLECTION_MEMBER_EXPRESSION_MISSING_COLLECTION_VALUED_PATH_EXPRESSION = A collection member expression must define a collection valued path expression.
+# CollectionMemberExpression - Semantic
+COLLECTION_MEMBER_EXPRESSION_EMBEDDABLE = An embeddable type is not supported.
+
+# CollectionMemberDeclaration - Grammar
+COLLECTION_MEMBER_DECLARATION_MISSING_COLLECTION_VALUED_PATH_EXPRESSION = The collection-valued path expression is missing from the collection member declaration.
+COLLECTION_MEMBER_DECLARATION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the collection member declaration.
+COLLECTION_MEMBER_DECLARATION_MISSING_IDENTIFICATION_VARIABLE = An identification variable must be specified for a collection member declaration.
+COLLECTION_MEMBER_DECLARATION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the collection member declaration.
+
+# CollectionValuedPathExpression - Semantic
+COLLECTION_VALUED_PATH_EXPRESSION_NOT_RESOLVABLE" ,     "The collection-valued path ''{0}'' cannot be resolved to a valid association field.
+COLLECTION_VALUED_PATH_EXPRESSION_NOT_COLLECTION_TYPE = The collection-valued path ''{0}'' must resolve to an association field.
+
+# ComparisonExpression - Grammar
+COMPARISON_EXPRESSION_MISSING_LEFT_EXPRESSION = A comparison expression must define the left side of the comparison.
+COMPARISON_EXPRESSION_MISSING_RIGHT_EXPRESSION = A comparison expression must define the right side of the comparison.
+# ComparisonExpression - Semantic
+COMPARISON_EXPRESSION_WRONG_COMPARISON_TYPE = The left and right expressions' type must be of the same type.
+
+# ConcatExpression - Grammar
+CONCAT_EXPRESSION_INVALID_EXPRESSION = The expression ''{0}'' is not valid expression.
+CONCAT_EXPRESSION_MISSING_EXPRESSION = The encapsulated expression is missing from the CONCAT expression.
+CONCAT_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the CONCAT expression.
+CONCAT_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the CONCAT expression.
+# ConcatExpression - Semantic
+CONCAT_EXPRESSION_EXPRESSION_WRONG_TYPE = The expression ''{0}'' is not a String.
+
+# ConstructorExpression - Grammar
+CONSTRUCTOR_EXPRESSION_CONSTRUCTOR_ITEM_ENDS_WITH_COMMA = The constructor items cannot end with a comma.
+CONSTRUCTOR_EXPRESSION_CONSTRUCTOR_ITEM_IS_MISSING_COMMA = The constructor expression has two constructor items (''{0}'' and ''{1}'') that are not separated by a comma.
+CONSTRUCTOR_EXPRESSION_MISSING_CONSTRUCTOR_ITEM = A constructor expression must define at least one constructor item.
+CONSTRUCTOR_EXPRESSION_MISSING_CONSTRUCTOR_NAME = The fully qualified class name must be specified.
+CONSTRUCTOR_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the constructor expression.
+CONSTRUCTOR_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the constructor expression.
+# ConstructorExpression - Semantic
+CONSTRUCTOR_EXPRESSION_MISMATCHED_PARAMETER_TYPES = No constructors can be found that match the argument types.
+CONSTRUCTOR_EXPRESSION_UNKNOWN_TYPE = ''{0}'' cannot be resolved to a type.
+
+# CountFunction - Grammar
+COUNT_FUNCTION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+COUNT_FUNCTION_MISSING_EXPRESSION = The encapsulated expression must be provided for a COUNT expression.
+COUNT_FUNCTION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the COUNT expression.
+COUNT_FUNCTION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the COUNT expression.
+# CountFunction - Semantic
+COUNT_FUNCTION_DISTINCT_EMBEDDABLE = The use of DISTINCT is not supported for arguments of embeddable types.
+
+# DateTime - Grammar
+DATE_TIME_JDBC_ESCAPE_FORMAT_INVALID_SPECIFICATION = The JDBC escape format does not start with either 'd', 't' or 'ts'.
+DATE_TIME_JDBC_ESCAPE_FORMAT_MISSING_CLOSE_QUOTE = The JDBC escape format is missing the close quote.
+DATE_TIME_JDBC_ESCAPE_FORMAT_MISSING_OPEN_QUOTE = The JDBC escape format is missing the open quote.
+DATE_TIME_JDBC_ESCAPE_FORMAT_MISSING_RIGHT_CURLY_BRACE = The JDBC escape format is missing the right curly brace.
+
+# DeleteClause - Grammar
+DELETE_CLAUSE_FROM_MISSING = The identifier FROM is missing from the DELETE FROM clause.
+DELETE_CLAUSE_MULTIPLE_RANGE_VARIABLE_DECLARATION = Only one entity abstract schema type can be defined.
+DELETE_CLAUSE_RANGE_VARIABLE_DECLARATION_MALFORMED = The entity abstract schema type declaration is malformed.
+DELETE_CLAUSE_RANGE_VARIABLE_DECLARATION_MISSING = A DELETE clause must define an entity abstract schema type.
+
+# DivisionExpression - Semantic
+DIVISION_EXPRESSION_LEFT_EXPRESSION_WRONG_TYPE = The left side of the division is not a valid arithmetic expression.
+DIVISION_EXPRESSION_RIGHT_EXPRESSION_WRONG_TYPE = The right side of the division is not a valid arithmetic expression.
+
+# EclipseLinkQueryBuilder - Validation
+ECLIPSE_LINK_QUERY_BUILDER_GRAMMAR_VALIDATOR_ERROR_MESSAGE = Syntax error parsing the query [{0}]. {1}
+ECLIPSE_LINK_QUERY_BUILDER_SEMANTIC_VALIDATOR_ERROR_MESSAGE = Problem compiling the query [{0}]. {1}
+
+# EncapsulatedIdentificationVariableExpression - Semantic
+ENCAPSULATED_IDENTIFICATION_VARIABLE_EXPRESSION_NOT_MAP_VALUED = The {0} operator may only be applied to identification variables that correspond to map-valued associations or map-valued element collections.
+
+# EmptyCollectionComparisonExpression - Grammar
+EMPTY_COLLECTION_COMPARISON_EXPRESSION_MISSING_EXPRESSION = The collection valued path expression must be defined.
+
+# EntityTypeLiteral - Semantic
+ENTITY_TYPE_LITERAL_NOT_RESOLVABLE = ''{0}'' cannot be resolved to a type.
+
+# EntryExpression - Grammar
+ENTRY_EXPRESSION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+ENTRY_EXPRESSION_MISSING_EXPRESSION = An identification variable must be provided for an ENTRY expression.
+ENTRY_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the ENTRY expression.
+ENTRY_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the ENTRY expression.
+
+# ExistsExpression - Grammar
+EXISTS_EXPRESSION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+EXISTS_EXPRESSION_MISSING_EXPRESSION = A subquery must be provided for an EXISTS expression.
+EXISTS_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the EXISTS expression.
+EXISTS_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the EXISTS expression.
+
+# FuncExpression - Grammar
+FUNC_EXPRESSION_MISSING_FUNCTION_NAME = The SQL function name must be specified.
+FUNC_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the FUNC expression.
+FUNC_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the FUNC expression.
+
+# GroupByClause - Grammar
+GROUP_BY_CLAUSE_GROUP_BY_ITEM_ENDS_WITH_COMMA = The select expression cannot end with a comma.
+GROUP_BY_CLAUSE_GROUP_BY_ITEM_IS_MISSING_COMMA = The GROUP BY clause has ''{0}'' and ''{1}'' that are not separated by a comma.
+GROUP_BY_CLAUSE_GROUP_BY_ITEM_MISSING = The grouping item is missing from the GROUP BY clause.
+
+# HavingClause - Grammar
+HAVING_CLAUSE_INVALID_CONDITIONAL_EXPRESSION = The expression is not a valid conditional expression.
+HAVING_CLAUSE_MISSING_CONDITIONAL_EXPRESSION = The conditional expression is missing from the HAVING clause.
+
+# IdentificationVariable - Grammar
+IDENTIFICATION_VARIABLE_INVALID_DUPLICATE = The identification variable ''{0}'' cannot be declared more than once.
+IDENTIFICATION_VARIABLE_INVALID_JAVA_IDENTIFIER = The identification variable ''{0}'' is not following the rules for a Java identifier.
+IDENTIFICATION_VARIABLE_INVALID_RESERVED_WORD = The identification variable ''{0}'' cannot be a reserved word.
+# IdentificationVariable - Semantic
+IDENTIFICATION_VARIABLE_ENTITY_NAME = An identification variable must not have the same name as any entity in the same persistence unit.
+IDENTIFICATION_VARIABLE_INVALID_NOT_DECLARED = The identification variable ''{0}'' is not defined in the FROM clause.
+
+# IdentificationVariableDeclaration - Grammar
+IDENTIFICATION_VARIABLE_DECLARATION_MISSING_RANGE_VARIABLE_DECLARATION = The range variable declaration must be specified.
+
+# IndexExpression - Grammar
+INDEX_EXPRESSION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+INDEX_EXPRESSION_MISSING_EXPRESSION = An identification variable must be provided for an INDEX expression.
+INDEX_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the INDEX expression.
+INDEX_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the INDEX expression.
+# IndexExpression - Semantic
+INDEX_EXPRESSION_WRONG_VARIABLE = The identification variable ''{0}'' does not represent an association or element collection.
+
+# InExpression - Grammar
+IN_EXPRESSION_IN_ITEM_ENDS_WITH_COMMA = The items cannot end with a comma.
+IN_EXPRESSION_IN_ITEM_IS_MISSING_COMMA = The IN expression has ''{0}'' and ''{1}'' that are not separated by a comma.
+IN_EXPRESSION_MALFORMED_EXPRESSION = The IN expression does not have a valid state field path expression or TYPE expession.
+IN_EXPRESSION_MISSING_IN_ITEMS = A least one item must be defined for the IN expression.
+IN_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the IN expression.
+IN_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the IN expression.
+IN_EXPRESSION_MISSING_EXPRESSION = A state field path expression or TYPE expression must be defined.
+
+# InputParameter - Grammar
+INPUT_PARAMETER_JAVA_IDENTIFIER = The named input parameter ''{0}'' is not following the rules for a Java identifier.
+INPUT_PARAMETER_MISSING_PARAMETER = The parameter value is missing from the input parameter.
+INPUT_PARAMETER_MIXTURE = Named and positional input parameters must not be mixed in a single query.
+INPUT_PARAMETER_NOT_INTEGER = The positional input parameter ''{0}'' cannot use non-Integer characters.
+INPUT_PARAMETER_SMALLER_THAN_ONE = The number used for the positional input parameter ''{0}'' must be greater than 0.
+INPUT_PARAMETER_WRONG_CLAUSE_DECLARATION = Input parameters can only be used in the WHERE clause or HAVING clause of a query.
+
+# Join - Grammar
+JOIN_MISSING_IDENTIFICATION_VARIABLE = An identification variable must be defined for a JOIN expression.
+JOIN_MISSING_JOIN_ASSOCIATION_PATH = The join association path is missing from the JOIN expression.
+
+# JoinFetch - Grammar
+JOIN_FETCH_MISSING_JOIN_ASSOCIATION_PATH = The join association path is missing from the JOIN FETCH expression.
+JOIN_FETCH_WRONG_CLAUSE_DECLARATION = JOIN FETCH expressions cannot be used in a FROM clause of a subquery.
+
+# JPQLExpression - Grammar
+JPQL_EXPRESSION_INVALID_QUERY = The query does not start with a valid identifier, has to be either SELECT, UPDATE or DELETE FROM.
+JPQL_EXPRESSION_UNKNOWN_ENDING = The query contains a malformed ending.
+
+# KeyExpression - Grammar
+KEY_EXPRESSION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+KEY_EXPRESSION_MISSING_EXPRESSION = The identification variable must be provided for an ABS expression.
+KEY_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the ABS expression.
+KEY_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the ABS expression.
+
+# LengthExpression - Grammar
+LENGTH_EXPRESSION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+LENGTH_EXPRESSION_MISSING_EXPRESSION = An expression must be provided for a LENGTH expression.
+LENGTH_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the LENGTH expression.
+LENGTH_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the LENGTH expression.
+# LikeExpression - Semantic
+LENGTH_EXPRESSION_WRONG_TYPE = The encapsulated expression is not of string type.
+
+# LikeExpression - Grammar
+LIKE_EXPRESSION_INVALID_ESCAPE_CHARACTER = {0} is not a valid escape character.
+LIKE_EXPRESSION_MISSING_ESCAPE_CHARACTER = The escape character is missing from the LIKE expression.
+LIKE_EXPRESSION_MISSING_PATTERN_VALUE = The pattern value is missing from the LIKE expression.
+LIKE_EXPRESSION_MISSING_STRING_EXPRESSION = The string expression is missing from the LIKE expression.
+
+# LocateExpression - Grammar
+LOCATE_EXPRESSION_INVALID_FIRST_EXPRESSION = The first argument is not a valid expression.
+LOCATE_EXPRESSION_INVALID_SECOND_EXPRESSION = The second argument is not a valid expression.
+LOCATE_EXPRESSION_INVALID_THIRD_EXPRESSION = The third argument is not a valid expression.
+LOCATE_EXPRESSION_MISSING_FIRST_EXPRESSION = The first argument is missing from the LOCATE expression.
+LOCATE_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the LOCATE expression.
+LOCATE_EXPRESSION_MISSING_FIRST_COMMA = The first comma is missing from the LOCATE expression.
+LOCATE_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the LOCATE expression.
+LOCATE_EXPRESSION_MISSING_SECOND_COMMA = The second comma is missing from the LOCATE expression.
+LOCATE_EXPRESSION_MISSING_SECOND_EXPRESSION = The second argument is missing from the LOCATE expression.
+LOCATE_EXPRESSION_MISSING_THIRD_EXPRESSION = The third argument is missing from the LOCATE expression.
+# LocateExpression - Semantic
+LOCATE_EXPRESSION_FIRST_EXPRESSION_WRONG_TYPE = The first expression is not of string type.
+LOCATE_EXPRESSION_SECOND_EXPRESSION_WRONG_TYPE = The second expression is not of string type.
+LOCATE_EXPRESSION_THIRD_EXPRESSION_WRONG_TYPE = The third encapsulated expression is not of numeric type.
+
+# LogicalExpression - Grammar
+LOGICAL_EXPRESSION_INVALID_LEFT_EXPRESSION = The left expression is missing from the logical expression.
+LOGICAL_EXPRESSION_INVALID_RIGHT_EXPRESSION = The right expression is missing from the logical expression.
+LOGICAL_EXPRESSION_MISSING_LEFT_EXPRESSION = The left expression is not a valid expression.
+LOGICAL_EXPRESSION_MISSING_RIGHT_EXPRESSION = The right expression is not a valid expression.
+
+# LowerExpression - Grammar
+LOWER_EXPRESSION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+LOWER_EXPRESSION_MISSING_EXPRESSION = An expression must be provided for a LOWER expression.
+LOWER_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the LOWER expression.
+LOWER_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the LOWER expression.
+# UpperExpression - Semantic
+LOWER_EXPRESSION_WRONG_TYPE = The expression is not a String.
+
+# MaxFunction - Grammar
+MAX_FUNCTION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+MAX_FUNCTION_MISSING_EXPRESSION = The encapsulated expression must be provided for a MAX expression.
+MAX_FUNCTION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the MAX expression.
+MAX_FUNCTION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the MAX expression.
+
+# MinFunction - Grammar
+MIN_FUNCTION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+MIN_FUNCTION_MISSING_EXPRESSION = The encapsulated expression must be provided for a MIN expression.
+MIN_FUNCTION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the MIN expression.
+MIN_FUNCTION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the MIN expression.
+
+# ModExpression - Grammar
+MOD_EXPRESSION_INVALID_FIRST_EXPRESSION = The first argument is not a valid expression.
+MOD_EXPRESSION_INVALID_SECOND_PARENTHESIS = The second argument is not a valid expression.
+MOD_EXPRESSION_MISSING_COMMA = The comma is missing from the MOD expression.
+MOD_EXPRESSION_MISSING_FIRST_EXPRESSION = The first argument is missing from the MOD expression.
+MOD_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the MOD expression.
+MOD_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the MOD expression.
+MOD_EXPRESSION_MISSING_SECOND_EXPRESSION = The second argument is missing from the MOD expression.
+# ModExpression - Semantic
+MOD_EXPRESSION_FIRST_EXPRESSION_WRONG_TYPE = The first expression is not an Integer.
+MOD_EXPRESSION_SECOND_EXPRESSION_WRONG_TYPE = The second expression is not an Integer.
+
+# MultiplicationExpression - Semantic
+MULTIPLICATION_EXPRESSION_LEFT_EXPRESSION_WRONG_TYPE = The left side of the multiplication is not a valid arithmetic expression.
+MULTIPLICATION_EXPRESSION_RIGHT_EXPRESSION_WRONG_TYPE = The right side of the multiplication is not a valid arithmetic expression.
+
+# NotExpression - Grammar
+NOT_EXPRESSION_MISSING_EXPRESSION = The expression is missing after the identifier NOT.
+# NotExpression - Semantic
+NOT_EXPRESSION_WRONG_TYPE = The expression is not of boolean type.
+
+# NullComparisonExpression - Grammar
+NULL_COMPARISON_EXPRESSION_MISSING_EXPRESSION = The expression is missing from the null comparison expression.
+# NullComparisonExpression - Semantic
+NULL_COMPARISON_EXPRESSION_INVALID_TYPE = ''{0}'' cannot be resolved to an embeddable.
+
+# NullIfExpression - Grammar
+NULL_IF_EXPRESSION_INVALID_FIRST_EXPRESSION = The first argument is not a valid expression.
+NULL_IF_EXPRESSION_INVALID_SECOND_EXPRESSION = The second argument is not a valid expression.
+NULL_IF_EXPRESSION_MISSING_COMMA = The comma is missing from the NULLIF expression.
+NULL_IF_EXPRESSION_MISSING_FIRST_EXPRESSION = The first argument is missing from the NULLIF expression.
+NULL_IF_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the NULLIF expression.
+NULL_IF_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the NULLIF expression.
+NULL_IF_EXPRESSION_MISSING_SECOND_EXPRESSION = The second argument is missing from the NULLIF expression.
+
+# NumericLiteral - Grammar
+NUMERIC_LITERAL_INVALID = ''{0}'' is not a valid numeric value.
+
+# ObjectByItem - Grammar
+ORDER_BY_ITEM_INVALID_PATH = ''{0}'' is not a valid state field path expression.
+ORDER_BY_ITEM_MISSING_STATE_FIELD_PATH_EXPRESSION = A state field path expression must be specified.
+
+# ObjectExpression - Grammar
+OBJECT_EXPRESSION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+OBJECT_EXPRESSION_MISSING_EXPRESSION = An identification variable must be provided for an OBJECT expression.
+OBJECT_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the OBJECT expression.
+OBJECT_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the OBJECT expression.
+
+# OrderByClause - Grammar
+ORDER_BY_CLAUSE_ORDER_BY_ITEM_ENDS_WITH_COMMA = The select expression cannot end with a comma.
+ORDER_BY_CLAUSE_ORDER_BY_ITEM_IS_MISSING_COMMA = The ORDER BY clause has ''{0}'' and ''{1}'' that are not separated by a comma.
+ORDER_BY_CLAUSE_ORDER_BY_ITEM_MISSING = The ordering item is missing from the ORDER BY clause.
+
+# RangeVariableDeclaration - Grammar
+RANGE_VARIABLE_DECLARATION_MISSING_ABSTRACT_SCHEMA_NAME = An abstract schema name must be specified.
+RANGE_VARIABLE_DECLARATION_MISSING_IDENTIFICATION_VARIABLE = An identification variable must be provider for a range variable declaration.
+
+# ResultVariable - Grammar
+RESULT_VARIABLE_MISSING_SELECT_EXPRESSION = The select item is missing from the result variable declaration.
+RESULT_VARIABLE_MISSING_RESULT_VARIABLE = The result variable is missing from the select item declaration.
+
+# SelectStatement - Semantic
+SELECT_STATEMENT_SELECT_CLAUSE_HAS_NON_AGGREGATE_FUNCTIONS = The select list can only consist of aggregate functions because there is no GROUP BY clause and the HAVING clause is used.
+
+# SimpleSelectClause - Grammar
+SIMPLE_SELECT_CLAUSE_NOT_SINGLE_EXPRESSION = Only one expression can be declared in a SELECT clause of a subquery.
+
+# SizeExpression - Grammar
+SIZE_EXPRESSION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+SIZE_EXPRESSION_MISSING_EXPRESSION = A collection-valued path expression must be provided for a SIZE expression.
+SIZE_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the SIZE expression.
+SIZE_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the SIZE expression.
+
+# SqrtExpression - Grammar
+SQRT_EXPRESSION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+SQRT_EXPRESSION_MISSING_EXPRESSION = An expression must be provided for a SQRT expression.
+SQRT_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the SQRT expression.
+SQRT_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the SQRT expression.
+# SqrtExpression - Semantic
+SQRT_EXPRESSION_WRONG_TYPE = The expression is not a numeric type.
+
+# StateFieldPathExpression - Semantic
+STATE_FIELD_PATH_EXPRESSION_ASSOCIATION_FIELD = The association field ''{0}'' cannot be used as a state field path.
+STATE_FIELD_PATH_EXPRESSION_COLLECTION_TYPE = The state field path ''{0}'' cannot be resolved to a collection type.
+STATE_FIELD_PATH_EXPRESSION_INVALID_ENUM_CONSTANT = ''{0}'' cannot be resolved to an Enum constant.
+STATE_FIELD_PATH_EXPRESSION_NO_MAPPING = No mapping is associated with the state field path ''{0}''.
+STATE_FIELD_PATH_EXPRESSION_NOT_RESOLVABLE = The state field path ''{0}'' cannot be resolved to a valid type.
+
+# SubExpression - Grammar
+SUB_EXPRESSION_MISSING_EXPRESSION = The encapsulated expression is missing.
+SUB_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the sub-expression.
+
+# SubstractionExpression - Semantic
+SUBTRACTION_EXPRESSION_LEFT_EXPRESSION_WRONG_TYPE = The left side of the subtraction is not a valid arithmetic expression.
+SUBTRACTION_EXPRESSION_RIGHT_EXPRESSION_WRONG_TYPE = The right side of the subtraction is not a valid arithmetic expression.
+
+# SubstringExpression - Grammar
+SUBSTRING_EXPRESSION_INVALID_FIRST_EXPRESSION = The first argument is not a valid expression.
+SUBSTRING_EXPRESSION_INVALID_SECOND_EXPRESSION = The second argument is not a valid expression.
+SUBSTRING_EXPRESSION_INVALID_THIRD_EXPRESSION = The third argument is not a valid expression.
+SUBSTRING_EXPRESSION_MISSING_FIRST_COMMA = The first comma is missing from the SUBSTRING expression.
+SUBSTRING_EXPRESSION_MISSING_FIRST_EXPRESSION = The first argument is missing from the SUBSTRING expression.
+SUBSTRING_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the SUBSTRING expression.
+SUBSTRING_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the SUBSTRING expression.
+SUBSTRING_EXPRESSION_MISSING_SECOND_COMMA = The second comma is missing from the SUBSTRING expression.
+SUBSTRING_EXPRESSION_MISSING_SECOND_EXPRESSION = The second argument is missing from the SUBSTRING expression.
+SUBSTRING_EXPRESSION_MISSING_THIRD_EXPRESSION = The third argument is missing from the SUBSTRING expression.
+# SubstringExpression - Semantic
+SUBSTRING_EXPRESSION_FIRST_EXPRESSION_WRONG_TYPE = The first argument is not a String value.
+SUBSTRING_EXPRESSION_SECOND_EXPRESSION_WRONG_TYPE = The first argument is not an integer value.
+SUBSTRING_EXPRESSION_THIRD_EXPRESSION_WRONG_TYPE = The first argument is not an integer value.
+
+# SumFunction - Grammar
+SUM_FUNCTION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+SUM_FUNCTION_MISSING_EXPRESSION = The encapsulated expression must be provided for a SUM expression.
+SUM_FUNCTION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the SUM expression.
+SUM_FUNCTION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the SUM expression.
+# SumFunction - Semantic
+SUM_FUNCTION_WRONG_TYPE = The argument must be numeric.
+
+# TrimExpression - Grammar
+TRIM_EXPRESSION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+TRIM_EXPRESSION_INVALID_TRIM_CHARACTER = The trim character should be a single-character string literal or a character-valued input parameter (i.e., char or Character).
+TRIM_EXPRESSION_MISSING_EXPRESSION = An expression must be provided for a TRIM expression.
+TRIM_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the TRIM expression.
+TRIM_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the TRIM expression.
+TRIM_EXPRESSION_NOT_SINGLE_STRING_LITERAL = The trim character should be a single-character string literal.
+
+# TypeExpression - Grammar
+TYPE_EXPRESSION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+TYPE_EXPRESSION_MISSING_EXPRESSION = An identification variable or a path expression must be provided for a TYPE expression.
+TYPE_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the TYPE expression.
+TYPE_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the TYPE expression.
+# TypeExpression - Semantic
+
+# UpdateClause - Grammar
+UPDATE_CLAUSE_MISSING_RANGE_VARIABLE_DECLARATION = The range variable declaration is missing from the UPDATE clause.
+UPDATE_CLAUSE_MISSING_SET = The SET identifier is missing from the UPDATE clause.
+UPDATE_CLAUSE_MISSING_UPDATE_ITEMS = At least one update item must be specified for an UPDATE clause.
+UPDATE_CLAUSE_UPDATE_ITEM_ENDS_WITH_COMMA = The update item cannot end with a comma.
+UPDATE_CLAUSE_UPDATE_ITEM_IS_MISSING_COMMA = The UPDATE clause has ''{0}'' and ''{1}'' that are not separated by a comma.
+
+# UpdateItem - Grammar
+UPDATE_ITEM_MISSING_EQUAL_SIGN = The equal sign must be specified.
+UPDATE_ITEM_MISSING_NEW_VALUE = The new value must be specified.
+UPDATE_ITEM_MISSING_STATE_FIELD_PATH_EXPRESSION = The state field path expression is missing.
+# UpdateItem - Semantic
+UPDATE_ITEM_NOT_ASSIGNABLE = Type mismatch: cannot convert from {0} to {1}.
+UPDATE_ITEM_NOT_RESOLVABLE = The state field cannot be resolved.
+
+# UpperExpression - Grammar
+UPPER_EXPRESSION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+UPPER_EXPRESSION_MISSING_EXPRESSION = An expression must be provided for a UPPER expression.
+UPPER_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the UPPER expression.
+UPPER_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the UPPER expression.
+# UpperExpression - Semantic
+UPPER_EXPRESSION_WRONG_TYPE = The expression is not a String.
+
+# ValueExpression - Grammar
+VALUE_EXPRESSION_INVALID_EXPRESSION = The encapsulated expression is not a valid expression.
+VALUE_EXPRESSION_MISSING_EXPRESSION = An identification variable must be provided for a VALUE expression.
+VALUE_EXPRESSION_MISSING_LEFT_PARENTHESIS = The left parenthesis is missing from the VALUE expression.
+VALUE_EXPRESSION_MISSING_RIGHT_PARENTHESIS = The right parenthesis is missing from the VALUE expression.
+
+# WhenClause - Grammar
+WHEN_CLAUSE_MISSING_THEN_EXPRESSION = A conditional expression must be provider for a WHEN clause.
+WHEN_CLAUSE_MISSING_THEN_IDENTIFIER = The identifier THEN is missing from the WHEN clause.
+WHEN_CLAUSE_MISSING_WHEN_EXPRESSION = A WHEN expression must be provided for a WHEN clause.
+
+# WhereClause - Grammar
+WHERE_CLAUSE_INVALID_CONDITIONAL_EXPRESSION = The expression is not a valid conditional expression.
+WHERE_CLAUSE_MISSING_CONDITIONAL_EXPRESSION = The conditional expression is missing from the WHERE clause.
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/context/orm/OrmNamedQuery.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/context/orm/OrmNamedQuery.java
index fc5aba3..5ca7624 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/context/orm/OrmNamedQuery.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/context/orm/OrmNamedQuery.java
@@ -21,7 +21,7 @@
  * stability. It is available at this early stage to solicit feedback from
  * pioneering adopters on the understanding that any code that uses this API
  * will almost certainly be broken (repeatedly) as the API evolves.
- * 
+ *
  * @version 2.1
  * @since 2.0
  */
@@ -32,4 +32,5 @@
 
 	// required to resolve ambiguity
 	ListIterable<OrmQueryHint> getHints();
-}
+
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/context/orm/OrmQuery.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/context/orm/OrmQuery.java
index 7275bea..c4e55a2 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/context/orm/OrmQuery.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/context/orm/OrmQuery.java
@@ -3,7 +3,7 @@
  * 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
  ******************************************************************************/
@@ -23,7 +23,7 @@
  * stability. It is available at this early stage to solicit feedback from
  * pioneering adopters on the understanding that any code that uses this API
  * will almost certainly be broken (repeatedly) as the API evolves.
- * 
+ *
  * @version 2.1
  * @since 2.0
  */
@@ -46,4 +46,6 @@
 	// ********** validation **********
 
 	TextRange getNameTextRange();
+
+	TextRange getQueryTextRange();
 }
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractOrmQuery.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractOrmQuery.java
index df72433..24afd7e 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractOrmQuery.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/context/orm/AbstractOrmQuery.java
@@ -10,8 +10,8 @@
 package org.eclipse.jpt.jpa.core.internal.context.orm;
 
 import java.util.Vector;
-
 import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.internal.StringTools;
 import org.eclipse.jpt.common.utility.internal.iterables.ListIterable;
 import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneIterable;
 import org.eclipse.jpt.common.utility.internal.iterables.LiveCloneListIterable;
@@ -25,6 +25,7 @@
 import org.eclipse.jpt.jpa.core.resource.orm.OrmFactory;
 import org.eclipse.jpt.jpa.core.resource.orm.XmlQuery;
 import org.eclipse.jpt.jpa.core.resource.orm.XmlQueryHint;
+import org.eclipse.persistence.jpa.jpql.ExpressionTools;
 
 /**
  * <code>orm.xml</code> query
@@ -47,18 +48,17 @@
 		super(parent);
 		this.xmlQuery = xmlQuery;
 		this.name = xmlQuery.getName();
-		this.query = xmlQuery.getQuery();
+		this.query = getUnescapeQuery();
 		this.initializeHints();
 	}
 
-
 	// ********** synchronize/update **********
 
 	@Override
-	public void synchronizeWithResourceModel() { 
+	public void synchronizeWithResourceModel() {
 		super.synchronizeWithResourceModel();
 		this.setName_(this.xmlQuery.getName());
-		this.setQuery_(this.xmlQuery.getQuery());
+		this.setQuery_(this.getUnescapeQuery());
 		this.syncHints();
 	}
 
@@ -96,7 +96,7 @@
 
 	public void setQuery(String query) {
 		this.setQuery_(query);
-		this.xmlQuery.setQuery(query);
+		this.xmlQuery.setQuery(this.convertToEscapeQuery(query));
 	}
 
 	protected void setQuery_(String query) {
@@ -105,6 +105,21 @@
 		this.firePropertyChanged(QUERY_PROPERTY, old, query);
 	}
 
+	protected String getUnescapeQuery() {
+		String query = this.xmlQuery.getQuery();
+		if (StringTools.stringIsNotEmpty(query)) {
+			query = ExpressionTools.unescape(query, new int[1]);
+		}
+		return query;
+	}
+
+	protected String convertToEscapeQuery(String query) {
+		if (StringTools.stringIsNotEmpty(query)) {
+			query = ExpressionTools.escape(query, new int[1]);
+		}
+		return query;
+	}
+
 
 	// ********** hints **********
 
@@ -231,9 +246,12 @@
 		return this.xmlQuery.getNameTextRange();
 	}
 
+	public TextRange getQueryTextRange() {
+		return this.xmlQuery.getQueryTextRange();
+	}
+
 	@Override
 	public void toString(StringBuilder sb) {
 		sb.append(this.name);
 	}
-
-}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaNamedQuery.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaNamedQuery.java
index 8c22d99..e1edc7b 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaNamedQuery.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaNamedQuery.java
@@ -1,18 +1,23 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2010 Oracle. All rights reserved.
+ * Copyright (c) 2007, 2011 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.
- * 
+ *
  * Contributors:
  *     Oracle - initial API and implementation
  ******************************************************************************/
 package org.eclipse.jpt.jpa.core.internal.jpa1.context.java;
 
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode;
 import org.eclipse.jpt.jpa.core.context.java.JavaNamedQuery;
 import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaQuery;
+import org.eclipse.jpt.jpa.core.internal.jpql.JpaJpqlQueryHelper;
 import org.eclipse.jpt.jpa.core.resource.java.NamedQueryAnnotation;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
 
 /**
  * Java named query
@@ -24,4 +29,18 @@
 	public GenericJavaNamedQuery(JavaJpaContextNode parent, NamedQueryAnnotation queryAnnotation) {
 		super(parent, queryAnnotation);
 	}
-}
+
+
+	// ********** validation **********
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+		super.validate(messages, reporter, astRoot);
+
+		JpaJpqlQueryHelper helper = new JpaJpqlQueryHelper();
+		helper.validate(this, this.getQuery(), this.getQueryAnnotation().getQueryTextRange(astRoot), 1, messages);
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaQueryContainer.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaQueryContainer.java
index 220db7e..c0c239b 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaQueryContainer.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/java/GenericJavaQueryContainer.java
@@ -308,10 +308,10 @@
 	@Override
 	public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
 		super.validate(messages, reporter, astRoot);
-		this.validateQueries(messages, astRoot);
+		this.validateQueries(messages, reporter, astRoot);
 	}
 
-	protected void validateQueries(List<IMessage> messages, CompilationUnit astRoot) {
+	protected void validateQueries(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
 		for (Iterator<JavaQuery> localQueries = this.queries(); localQueries.hasNext(); ) {
 			JavaQuery localQuery = localQueries.next();
 			String name = localQuery.getName();
@@ -354,6 +354,9 @@
 						)
 				);
 			}
+			else {
+				localQuery.validate(messages, reporter, astRoot);
+			}
 		}
 	}
 
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmNamedQuery.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmNamedQuery.java
index 35ef252..bc24b97 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmNamedQuery.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmNamedQuery.java
@@ -1,18 +1,23 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2010 Oracle. All rights reserved.
+ * Copyright (c) 2007, 2011 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.
- * 
+ *
  * Contributors:
  *     Oracle - initial API and implementation
  ******************************************************************************/
 package org.eclipse.jpt.jpa.core.internal.jpa1.context.orm;
 
+import java.util.List;
 import org.eclipse.jpt.jpa.core.context.XmlContextNode;
 import org.eclipse.jpt.jpa.core.context.orm.OrmNamedQuery;
 import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmQuery;
+import org.eclipse.jpt.jpa.core.internal.jpql.JpaJpqlQueryHelper;
 import org.eclipse.jpt.jpa.core.resource.orm.XmlNamedQuery;
+import org.eclipse.persistence.jpa.jpql.ExpressionTools;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
 
 /**
  * <code>orm.xml</code> named query
@@ -24,4 +29,20 @@
 	public GenericOrmNamedQuery(XmlContextNode parent, XmlNamedQuery resourceNamedQuery) {
 		super(parent, resourceNamedQuery);
 	}
-}
+
+	// ********** validation **********
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void validate(List<IMessage> messages, IReporter reporter) {
+		super.validate(messages, reporter);
+
+		// Convert the literal escape characters into actual escape characters
+		String jpqlQuery = ExpressionTools.unescape(this.getQuery(), new int[1]);
+
+		JpaJpqlQueryHelper helper = new JpaJpqlQueryHelper();
+		helper.validate(this, jpqlQuery, this.getQueryTextRange(), 0, messages);
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmQueryContainer.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmQueryContainer.java
index c4858f9..70fbb54 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmQueryContainer.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa1/context/orm/GenericOrmQueryContainer.java
@@ -14,7 +14,6 @@
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Vector;
-
 import org.eclipse.jpt.common.core.utility.TextRange;
 import org.eclipse.jpt.common.utility.internal.StringTools;
 import org.eclipse.jpt.common.utility.internal.iterables.CompositeIterable;
@@ -300,10 +299,10 @@
 	@Override
 	public void validate(List<IMessage> messages, IReporter reporter) {
 		super.validate(messages, reporter);
-		this.validateQueries(messages);
+		this.validateQueries(messages, reporter);
 	}
 
-	protected void validateQueries(List<IMessage> messages) {
+	protected void validateQueries(List<IMessage> messages, IReporter reporter) {
 		for (OrmQuery localQuery : this.getQueries()) {
 			String name = localQuery.getName();
 			if (StringTools.stringIsEmpty(name)){
@@ -345,6 +344,9 @@
 						)
 				);
 			}
+			else {
+				localQuery.validate(messages, reporter);
+			}
 		}
 	}
 
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa2/context/java/GenericJavaNamedQuery2_0.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa2/context/java/GenericJavaNamedQuery2_0.java
index 5b168c3..9392b4b 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa2/context/java/GenericJavaNamedQuery2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa2/context/java/GenericJavaNamedQuery2_0.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
-* Copyright (c) 2009, 2010 Oracle. All rights reserved.
+* Copyright (c) 2009, 2011 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.
@@ -9,11 +9,16 @@
 *******************************************************************************/
 package org.eclipse.jpt.jpa.core.internal.jpa2.context.java;
 
+import java.util.List;
+import org.eclipse.jdt.core.dom.CompilationUnit;
 import org.eclipse.jpt.jpa.core.context.java.JavaJpaContextNode;
 import org.eclipse.jpt.jpa.core.internal.context.java.AbstractJavaQuery;
+import org.eclipse.jpt.jpa.core.internal.jpql.JpaJpqlQueryHelper;
 import org.eclipse.jpt.jpa.core.jpa2.context.LockModeType2_0;
 import org.eclipse.jpt.jpa.core.jpa2.context.java.JavaNamedQuery2_0;
 import org.eclipse.jpt.jpa.core.jpa2.resource.java.NamedQuery2_0Annotation;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
 
 /**
  * JPA 2.0
@@ -87,4 +92,17 @@
 		return LockModeType2_0.NONE;
 	}
 
-}
+
+	// ********** validation **********
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void validate(List<IMessage> messages, IReporter reporter, CompilationUnit astRoot) {
+		super.validate(messages, reporter, astRoot);
+
+		JpaJpqlQueryHelper helper = new JpaJpqlQueryHelper();
+		helper.validate(this, this.getQuery(), this.getQueryAnnotation().getQueryTextRange(astRoot), 1, messages);
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa2/context/orm/GenericOrmNamedQuery2_0.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa2/context/orm/GenericOrmNamedQuery2_0.java
index 639bf61..4bc9d37 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa2/context/orm/GenericOrmNamedQuery2_0.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpa2/context/orm/GenericOrmNamedQuery2_0.java
@@ -1,19 +1,24 @@
 /*******************************************************************************
- * Copyright (c) 2007, 2010 Oracle. All rights reserved.
+ * Copyright (c) 2007, 2011 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.
- * 
+ *
  * Contributors:
  *     Oracle - initial API and implementation
  ******************************************************************************/
 package org.eclipse.jpt.jpa.core.internal.jpa2.context.orm;
 
+import java.util.List;
 import org.eclipse.jpt.jpa.core.context.XmlContextNode;
 import org.eclipse.jpt.jpa.core.internal.context.orm.AbstractOrmQuery;
+import org.eclipse.jpt.jpa.core.internal.jpql.JpaJpqlQueryHelper;
 import org.eclipse.jpt.jpa.core.jpa2.context.LockModeType2_0;
 import org.eclipse.jpt.jpa.core.jpa2.context.orm.OrmNamedQuery2_0;
 import org.eclipse.jpt.jpa.core.resource.orm.XmlNamedQuery;
+import org.eclipse.persistence.jpa.jpql.ExpressionTools;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+import org.eclipse.wst.validation.internal.provisional.core.IReporter;
 
 /**
  * JPA 2.0
@@ -87,4 +92,19 @@
 		return LockModeType2_0.NONE;
 	}
 
-}
+	// ********** validation **********
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void validate(List<IMessage> messages, IReporter reporter) {
+		super.validate(messages, reporter);
+
+		// Convert the literal escape characters into actual escape characters
+		String jpqlQuery = ExpressionTools.unescape(this.getQuery(), new int[1]);
+
+		JpaJpqlQueryHelper helper = new JpaJpqlQueryHelper();
+		helper.validate(this, jpqlQuery, this.getQueryTextRange(), 0, messages);
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/ClassConstructor.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/ClassConstructor.java
new file mode 100644
index 0000000..ffff5e0
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/ClassConstructor.java
@@ -0,0 +1,143 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import org.eclipse.jdt.core.BindingKey;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.Signature;
+import org.eclipse.persistence.jpa.jpql.spi.IConstructor;
+import org.eclipse.persistence.jpa.jpql.spi.IType;
+import org.eclipse.persistence.jpa.jpql.spi.ITypeDeclaration;
+import org.eclipse.persistence.jpa.jpql.spi.ITypeRepository;
+
+/**
+ * The concrete implementation of {@link IConstructor} that is wrapping the {@link IMethod}
+ * representation of a Java constructor (either coming from a Java compiled file or a Java source
+ * file).
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+final class ClassConstructor implements IConstructor {
+
+	/**
+	 * The information of the constructor.
+	 */
+	private IMethod method;
+
+	/**
+	 * The declaring type of this constructor.
+	 */
+	private JpaType type;
+
+	/**
+	 * The cached {@link ITypeDeclaration ITypeDeclarations} representing each of the constructor's
+	 * parameter types.
+	 */
+	private ITypeDeclaration[] typeDeclarations;
+
+	/**
+	 * Creates a new <code>ClassConstructor</code>.
+	 *
+	 * @param type The declaring type of this constructor
+	 * @param methodInfo The information of the constructor
+	 */
+	ClassConstructor(JpaType type, IMethod method) {
+		super();
+		this.type   = type;
+		this.method = method;
+	}
+
+	private ITypeDeclaration[] buildParameterTypes() {
+
+		BindingKey bindingKey = new BindingKey(method.getKey());
+		String signature = bindingKey.toSignature();
+
+		int count = Signature.getParameterCount(signature);
+		ITypeDeclaration[] typeDeclarations = new ITypeDeclaration[count];
+		int index = 0;
+
+		for (String parameterType : Signature.getParameterTypes(signature)) {
+
+			// 1. Retrieve the parameter type (without the type parameters)
+			String parameterTypeName = Signature.getTypeErasure(parameterType);
+
+			// 3. Convert the type signature to a dot-based name
+			parameterTypeName = Signature.toString(parameterTypeName);
+
+			// 4. Create the ITypeDeclaration
+			typeDeclarations[index++] = new JpaTypeDeclaration(
+				getTypeRepository().getType(parameterTypeName),
+				buildTypeParameters(parameterType),
+				Signature.getArrayCount(parameterType)
+			);
+		}
+
+		return typeDeclarations;
+	}
+
+	private ITypeDeclaration[] buildTypeParameters(String signature) {
+
+		String[] typeParameters = Signature.getTypeArguments(signature);
+		ITypeDeclaration[] generics = new ITypeDeclaration[typeParameters.length];
+
+		for (int index = 0; index < typeParameters.length; index++) {
+			String typeParameter = typeParameters[index];
+
+			// 1. Retrieve the parameter type (without the wild cards)
+			switch (Signature.getTypeSignatureKind(typeParameter)) {
+				case Signature.WILDCARD_TYPE_SIGNATURE: {
+					typeParameter = typeParameter.substring(1);
+				}
+			}
+
+			if (typeParameter.length() == 0) {
+				generics[index] = getTypeRepository().getTypeHelper().objectTypeDeclaration();
+			}
+			else {
+				String typeParameterName = Signature.getTypeErasure(typeParameter);
+
+				// 3. Convert the type signature to a dot-based name
+				typeParameterName = Signature.toString(typeParameterName);
+
+				// 3. Retrieve the IType for the type parameter
+				IType genericType = getTypeRepository().getType(typeParameterName);
+
+				if (genericType.isResolvable()) {
+					generics[index] = genericType.getTypeDeclaration();
+				}
+				else {
+					generics[index] = getTypeRepository().getTypeHelper().objectTypeDeclaration();
+				}
+			}
+		}
+
+		return generics;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public ITypeDeclaration[] getParameterTypes() {
+		if (typeDeclarations == null) {
+			typeDeclarations = buildParameterTypes();
+		}
+		return typeDeclarations;
+	}
+
+	private ITypeRepository getTypeRepository() {
+		return type.getTypeRepository();
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/IJpaType.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/IJpaType.java
new file mode 100644
index 0000000..0d914a9
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/IJpaType.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import org.eclipse.persistence.jpa.jpql.spi.IType;
+
+/**
+ * An internal interface used by all 3 implementations of {@link IType}.
+ *
+ * @see JavaType
+ * @see JpaType
+ * @see SimpleType
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+interface IJpaType extends IType {
+
+	/**
+	 * Manually sets the declaration of this {@link IType}, which gives the information about type
+	 * parameters, dimensionality, etc.
+	 *
+	 * @param typeDeclaration The external form of the type declaration
+	 */
+	void setTypeDeclaration(JpaTypeDeclaration typeDeclaration);
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JavaConstructor.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JavaConstructor.java
new file mode 100644
index 0000000..63a63a8
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JavaConstructor.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Type;
+import org.eclipse.persistence.jpa.jpql.spi.IConstructor;
+import org.eclipse.persistence.jpa.jpql.spi.IType;
+import org.eclipse.persistence.jpa.jpql.spi.ITypeDeclaration;
+import org.eclipse.persistence.jpa.jpql.spi.ITypeRepository;
+
+/**
+ * The concrete implementation of {@link IConstructor} that is wrapping a Java constructor.
+ *
+ * @version 2.3
+ * @since 2.3
+ * @author Pascal Filion
+ */
+final class JavaConstructor implements IConstructor {
+
+	/**
+	 * The actual Java constructor.
+	 */
+	private Constructor<?> constructor;
+
+	/**
+	 * The cached {@link ITypeDeclaration parameter types}.
+	 */
+	private ITypeDeclaration[] parameterTypes;
+
+	/**
+	 * The declaring type of this constructor.
+	 */
+	private JavaType type;
+
+	/**
+	 * Creates a new <code>JavaConstructor</code>.
+	 *
+	 * @param type The declaring type of this constructor
+	 * @param constructor The actual Java constructor
+	 */
+	JavaConstructor(JavaType type, Constructor<?> constructor) {
+		super();
+		this.type = type;
+		this.constructor = constructor;
+	}
+
+	private ITypeDeclaration[] buildParameterTypes() {
+
+		Class<?>[] types = constructor.getParameterTypes();
+		Type[] genericTypes = constructor.getGenericParameterTypes();
+		ITypeDeclaration[] typeDeclarations = new ITypeDeclaration[types.length];
+
+		for (int index = 0, count = types.length; index < count; index++) {
+			typeDeclarations[index] = buildTypeDeclaration(types[index], genericTypes[index]);
+		}
+
+		return typeDeclarations;
+	}
+
+	private ITypeDeclaration buildTypeDeclaration(Class<?> javaType, Type genericType) {
+		ITypeRepository typeRepository = getTypeRepository();
+		IType type = typeRepository.getType(javaType);
+		return new JavaTypeDeclaration(typeRepository, type, genericType, javaType.isArray());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public ITypeDeclaration[] getParameterTypes() {
+		if (parameterTypes == null) {
+			parameterTypes = buildParameterTypes();
+		}
+		return parameterTypes;
+	}
+
+	private ITypeRepository getTypeRepository() {
+		return type.getTypeRepository();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		return constructor.toGenericString();
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JavaType.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JavaType.java
new file mode 100644
index 0000000..517e08c
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JavaType.java
@@ -0,0 +1,246 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import org.eclipse.persistence.jpa.jpql.ExpressionTools;
+import org.eclipse.persistence.jpa.jpql.spi.IConstructor;
+import org.eclipse.persistence.jpa.jpql.spi.IType;
+import org.eclipse.persistence.jpa.jpql.spi.ITypeDeclaration;
+import org.eclipse.persistence.jpa.jpql.spi.ITypeRepository;
+
+/**
+ * The concrete implementation of {@link IType} that is wrapping a Java type.
+ *
+ * @version 2.3
+ * @since 2.3
+ * @author Pascal Filion
+ */
+final class JavaType implements IJpaType {
+
+	/**
+	 * The cached {@link IConstructor IConstructors}.
+	 */
+	private Collection<IConstructor> constructors;
+
+	/**
+	 * The list of names for the {@link Enum}'s constants otherwise an empty array.
+	 */
+	private String[] enumConstants;
+
+	/**
+	 * The actual Java type.
+	 */
+	private Class<?> type;
+
+	/**
+	 * The cached {@link ITypeDeclaration} for this {@link IType}.
+	 */
+	private ITypeDeclaration typeDeclaration;
+
+	/**
+	 * The fully qualified name of the Java type.
+	 */
+	private String typeName;
+
+	/**
+	 * The external form of a type repository.
+	 */
+	private ITypeRepository typeRepository;
+
+	/**
+	 * Creates a new <code>JavaType</code>.
+	 *
+	 * @param typeRepository The external form of a type repository
+	 * @param type The actual Java type wrapped by this class
+	 */
+	JavaType(ITypeRepository typeRepository, Class<?> type) {
+		super();
+		this.type           = type;
+		this.typeName       = type.getName();
+		this.typeRepository = typeRepository;
+	}
+
+	private IConstructor buildConstructor(Constructor<?> constructor) {
+		return new JavaConstructor(this, constructor);
+	}
+
+	private Collection<IConstructor> buildConstructors() {
+
+		Constructor<?>[] javaConstructors = type.getDeclaredConstructors();
+		Collection<IConstructor> constructors = new ArrayList<IConstructor>(javaConstructors.length);
+
+		for (Constructor<?> javaConstructor : javaConstructors) {
+			constructors.add(buildConstructor(javaConstructor));
+		}
+
+		return constructors;
+	}
+
+	private String[] buildEnumConstants() {
+
+		if (!type.isEnum()) {
+			return ExpressionTools.EMPTY_STRING_ARRAY;
+		}
+
+		Object[] enumConstants = type.getEnumConstants();
+		String[] names = new String[enumConstants.length];
+
+		for (int index = enumConstants.length; --index >= 0; ) {
+			names[index] = ((Enum<?>) enumConstants[index]).name();
+		}
+
+		return names;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Iterable<IConstructor> constructors() {
+		if (constructors == null) {
+			constructors = buildConstructors();
+		}
+		return Collections.unmodifiableCollection(constructors);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean equals(IType type) {
+		return (this == type) ? true : typeName.equals(type.getName());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean equals(Object object) {
+		return (this == object) || equals((IType) object);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String[] getEnumConstants() {
+		if (enumConstants == null) {
+			enumConstants = buildEnumConstants();
+		}
+		return enumConstants;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String getName() {
+		return typeName;
+	}
+
+	/**
+	 * Returns the encapsulated {@link Class}, which is the actual type.
+	 *
+	 * @return The actual Java type, if <code>null</code> is returned; then the class could not be resolved
+	 */
+	Class<?> getType() {
+		return type;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public ITypeDeclaration getTypeDeclaration() {
+		if (typeDeclaration == null) {
+			typeDeclaration = new JavaTypeDeclaration(typeRepository, this, null, (type != null) ? type.isArray() : false);
+		}
+		return typeDeclaration;
+	}
+
+	/**
+	 * Returns the type repository for the application.
+	 *
+	 * @return The repository of {@link IType ITypes}
+	 */
+	ITypeRepository getTypeRepository() {
+		return typeRepository;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean hasAnnotation(Class<? extends Annotation> annotationType) {
+		return type.isAnnotationPresent(annotationType);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public int hashCode() {
+		return typeName.hashCode();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isAssignableTo(IType type) {
+
+		if (this == type) {
+			return true;
+		}
+
+		// TODO
+		if (type instanceof JavaType) {
+			Class<?> otherType = ((JavaType) type).type;
+			return otherType.isAssignableFrom(this.type);
+		}
+		else if (type instanceof JpaType) {
+			// TODO
+			return false;
+		}
+
+		return false;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isEnum() {
+		return (type != null) && type.isEnum();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isResolvable() {
+		return true;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void setTypeDeclaration(JpaTypeDeclaration typeDeclaration) {
+		this.typeDeclaration = typeDeclaration;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		return typeName;
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JavaTypeDeclaration.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JavaTypeDeclaration.java
new file mode 100644
index 0000000..d33231a
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JavaTypeDeclaration.java
@@ -0,0 +1,271 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.persistence.jpa.jpql.spi.IType;
+import org.eclipse.persistence.jpa.jpql.spi.ITypeDeclaration;
+import org.eclipse.persistence.jpa.jpql.spi.ITypeRepository;
+
+/**
+ * The concrete implementation of {@link ITypeDeclaration} that is wrapping the representation
+ * of the declaration description of a type.
+ *
+ * @see IMapping
+ * @see IType
+ *
+ * @version 2.3
+ * @since 2.3
+ * @author Pascal Filion
+ */
+@SuppressWarnings("nls")
+final class JavaTypeDeclaration implements ITypeDeclaration {
+
+	/**
+	 * Determines whether the type declaration represents an array.
+	 */
+	private boolean array;
+
+	/**
+	 * The actual type that contains the generics, if any is present.
+	 */
+	private Object genericType;
+
+	/**
+	 * The cached {@link ITypeDeclaration ITypeDeclarations} representing the generics of the {@link
+	 * Type}.
+	 */
+	private ITypeDeclaration[] genericTypes;
+
+	/**
+	 * The external form of the Java type.
+	 */
+	private final IType type;
+
+	/**
+	 * The repository of {@link IType ITypes}.
+	 */
+	private ITypeRepository typeRepository;
+
+	/**
+	 * Creates a new <code>JavaTypeDeclaration</code>.
+	 *
+	 * @param typeRepository The repository of {@link IType ITypes}
+	 * @param type The external form of the Java type
+	 * @param genericType The actual type that contains the generics, if any is present
+	 * @param array Determines whether the type declaration represents an array
+	 */
+	JavaTypeDeclaration(ITypeRepository typeRepository,
+	                    IType type,
+	                    Object genericType,
+	                    boolean array) {
+
+		super();
+		this.type           = type;
+		this.array          = array;
+		this.genericType    = genericType;
+		this.typeRepository = typeRepository;
+	}
+
+	private String buildArrayTypeName(String arrayTypeName) {
+
+		StringBuilder sb = new StringBuilder();
+		int index = arrayTypeName.indexOf('[');
+		int dimensionality = (arrayTypeName.length() - index) / 2;
+		String typeName = arrayTypeName.substring(0, index);
+
+		while (--dimensionality >= 0) {
+			sb.append("[");
+		}
+
+		String elementType = elementType(typeName);
+
+		sb.append(elementType);
+		sb.append(typeName);
+
+		if (elementType.equals("L")) {
+			sb.append(";");
+		}
+
+		return sb.toString();
+	}
+
+	private ITypeDeclaration[] buildParameterTypes() {
+
+		List<ITypeDeclaration> parameterTypes = new ArrayList<ITypeDeclaration>();
+
+		// Example: Class<T>
+		if (genericType instanceof ParameterizedType) {
+			ParameterizedType parameterizedType = (ParameterizedType) genericType;
+			for (Type type : parameterizedType.getActualTypeArguments()) {
+				ITypeDeclaration typeParameter = buildTypeDeclaration(type);
+				parameterTypes.add(typeParameter);
+			}
+		}
+		// T[]
+		else if (genericType instanceof GenericArrayType) {
+			GenericArrayType genericArrayType = (GenericArrayType) genericType;
+			parameterTypes.add(buildTypeDeclaration(genericArrayType.getGenericComponentType()));
+		}
+		// Example: Class
+		else if (genericType.getClass() == Class.class) {
+			ITypeDeclaration typeParameter = buildTypeDeclaration((Class<?>) genericType);
+			parameterTypes.add(typeParameter);
+		}
+		// Example: <K, V>
+		else if (genericType.getClass() == Class[].class) {
+			for (Class<?> javaType : ((Class<?>[]) genericType)) {
+				ITypeDeclaration typeParameter = buildTypeDeclaration(javaType);
+				parameterTypes.add(typeParameter);
+			}
+		}
+		// Example: <K, V>
+		else if (genericType.getClass() == IType[].class) {
+			for (IType type : ((IType[]) genericType)) {
+				ITypeDeclaration typeParameter = new JavaTypeDeclaration(typeRepository, type, null, false);
+				parameterTypes.add(typeParameter);
+			}
+		}
+
+		return parameterTypes.toArray(new ITypeDeclaration[parameterTypes.size()]);
+	}
+
+	private JavaTypeDeclaration buildTypeDeclaration(Class<?> javaType) {
+		return new JavaTypeDeclaration(
+			typeRepository,
+			getType(javaType),
+			null,
+			javaType.isArray()
+		);
+	}
+
+	private JavaTypeDeclaration buildTypeDeclaration(Object genericType) {
+
+		// <T1, ..., Tn>
+		if (genericType instanceof ParameterizedType) {
+			ParameterizedType parameterizedType = (ParameterizedType) genericType;
+			return buildTypeDeclaration(parameterizedType.getRawType());
+		}
+
+		// <T>
+		if (genericType instanceof TypeVariable) {
+			TypeVariable<?> typeVariable = (TypeVariable<?>) genericType;
+			for (Type type : typeVariable.getBounds()) {
+				return buildTypeDeclaration(type);
+			}
+			return buildTypeDeclaration(Object.class);
+		}
+
+		// ?
+		if (genericType instanceof WildcardType) {
+			WildcardType wildcardType = (WildcardType) genericType;
+			for (Type type : wildcardType.getUpperBounds()) {
+				return buildTypeDeclaration(type);
+			}
+			return buildTypeDeclaration(Object.class);
+		}
+
+		// T[]
+		if (genericType instanceof GenericArrayType) {
+			GenericArrayType genericArrayType = (GenericArrayType) genericType;
+			String arrayTypeName = buildArrayTypeName(genericArrayType.toString());
+			IType arrayType = typeRepository.getType(arrayTypeName);
+
+			return new JavaTypeDeclaration(
+				typeRepository,
+				arrayType,
+				genericArrayType.getGenericComponentType(),
+				true
+			);
+		}
+
+		return buildTypeDeclaration((Class<?>) genericType);
+	}
+
+	private String elementType(String typeName) {
+
+		if (typeName.equals("boolean")) return "Z";
+		if (typeName.equals("byte"))    return "B";
+		if (typeName.equals("char"))    return "C";
+		if (typeName.equals("double"))  return "D";
+		if (typeName.equals("float"))   return "F";
+		if (typeName.equals("int"))     return "I";
+		if (typeName.equals("long"))    return "J";
+		if (typeName.equals("short"))   return "S";
+
+		return "L";
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public int getDimensionality() {
+		if (array) {
+			String name = type.getName();
+			int index = 0;
+			while (name.charAt(index) == '[') {
+				index++;
+			}
+			return index;
+		}
+		return 0;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IType getType() {
+		return type;
+	}
+
+	private IType getType(Class<?> type) {
+		return typeRepository.getType(type);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public ITypeDeclaration[] getTypeParameters() {
+		if (genericTypes == null) {
+			if (genericType == null) {
+				genericTypes = new ITypeDeclaration[0];
+			}
+			else {
+				genericTypes = buildParameterTypes();
+			}
+		}
+		return genericTypes;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isArray() {
+		return array;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		return (genericType != null) ? genericType.toString() : type.toString();
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaConstructor.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaConstructor.java
new file mode 100644
index 0000000..001937b
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaConstructor.java
@@ -0,0 +1,140 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import org.eclipse.jdt.core.dom.IMethodBinding;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.persistence.jpa.jpql.spi.IConstructor;
+import org.eclipse.persistence.jpa.jpql.spi.IType;
+import org.eclipse.persistence.jpa.jpql.spi.ITypeDeclaration;
+import org.eclipse.persistence.jpa.jpql.spi.ITypeRepository;
+
+/**
+ * The concrete implementation of {@link IConstructor} that is wrapping the design-time
+ * representation of a Java constructor.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+final class JpaConstructor implements IConstructor {
+
+	/**
+	 * The design-time representation of a Java constructor.
+	 */
+	private IMethodBinding constructor;
+
+	/**
+	 * The cached {@link ITypeDeclaration ITypeDeclarations} representing each of the constructor's
+	 * parameter types.
+	 */
+	private ITypeDeclaration[] typeDeclarations;
+
+	/**
+	 * The type owning this constructor.
+	 */
+	private JpaType type;
+
+	/**
+	 * Creates a new <code>JpaConstructor</code>.
+	 *
+	 * @param type The type owning the constructor
+	 * @param constructor The design-time representation of a Java constructor
+	 */
+	JpaConstructor(JpaType type, IMethodBinding constructor) {
+		super();
+		this.type        = type;
+		this.constructor = constructor;
+	}
+
+	private ITypeDeclaration buildTypeDeclaration(ITypeBinding parameterType) {
+
+		boolean array = parameterType.isArray();
+		String typeParameterName;
+
+		if (array) {
+			ITypeBinding componentType = parameterType.getComponentType();
+
+			// <T>[] or <? extends <class_name>>[]
+			if (componentType.isTypeVariable() ||
+			    componentType.isParameterizedType()) {
+
+				typeParameterName = componentType.getErasure().getQualifiedName();
+			}
+			else {
+				typeParameterName = componentType.getQualifiedName();
+			}
+
+			// Now for the type arguments, we have to use the component type
+			parameterType = componentType;
+		}
+		// <T> or <? extends <class_name>>
+		else if (parameterType.isTypeVariable() ||
+		         parameterType.isParameterizedType()) {
+
+			typeParameterName = parameterType.getErasure().getQualifiedName();
+		}
+		else {
+			typeParameterName = parameterType.getQualifiedName();
+		}
+
+		// Retrieve the fully qualified name of the type
+		ITypeRepository typeRepository = type.getTypeRepository();
+		ITypeBinding[] typeArguments = parameterType.getTypeArguments();
+		ITypeDeclaration[] genericTypes = new ITypeDeclaration[typeArguments.length];
+		int index = 0;
+
+		for (ITypeBinding typeArgument : typeArguments) {
+			String genericTypeName = typeArgument.getErasure().getQualifiedName();
+			IType genericType = typeRepository.getType(genericTypeName);
+			genericTypes[index++] = genericType.getTypeDeclaration();
+		}
+
+		return new JpaTypeDeclaration(
+			typeRepository.getType(typeParameterName),
+			genericTypes,
+			parameterType.getDimensions()
+		);
+	}
+
+	private ITypeDeclaration[] buildTypeDeclarations() {
+
+		ITypeBinding[] parameterTypes = constructor.getParameterTypes();
+		ITypeDeclaration[] declarations = new ITypeDeclaration[parameterTypes.length];
+
+		for (int index = declarations.length; --index >= 0; ) {
+			declarations[index] = buildTypeDeclaration(parameterTypes[index]);
+		}
+
+		return declarations;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public ITypeDeclaration[] getParameterTypes() {
+		if (typeDeclarations == null) {
+			typeDeclarations = buildTypeDeclarations();
+		}
+		return typeDeclarations;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		return constructor.toString();
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaEmbeddable.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaEmbeddable.java
new file mode 100644
index 0000000..2bbf9b4
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaEmbeddable.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import org.eclipse.jpt.jpa.core.context.Embeddable;
+import org.eclipse.persistence.jpa.jpql.spi.IEmbeddable;
+import org.eclipse.persistence.jpa.jpql.spi.IManagedTypeVisitor;
+
+/**
+ * The concrete implementation of {@link IEmbeddable} that is wrapping the design-time
+ * representation of a JPA embeddable.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+final class JpaEmbeddable extends JpaManagedType
+                          implements IEmbeddable {
+
+	/**
+	 * Creates a new <code>JpaEmbeddable</code>.
+	 *
+	 * @param provider The provider of JPA managed types
+	 * @param embeddable The design-time model object wrapped by this class
+	 */
+	JpaEmbeddable(JpaManagedTypeProvider provider, Embeddable embeddable) {
+		super(provider, embeddable);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void accept(IManagedTypeVisitor visitor) {
+		visitor.visit(this);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	Embeddable getManagedType() {
+		return (Embeddable) super.getManagedType();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		return getType().getName();
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaEntity.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaEntity.java
new file mode 100644
index 0000000..2f992ee
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaEntity.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import java.util.HashMap;
+import java.util.ListIterator;
+import java.util.Map;
+import org.eclipse.jpt.jpa.core.context.Entity;
+import org.eclipse.jpt.jpa.core.context.NamedQuery;
+import org.eclipse.persistence.jpa.jpql.spi.IEntity;
+import org.eclipse.persistence.jpa.jpql.spi.IManagedTypeVisitor;
+import org.eclipse.persistence.jpa.jpql.spi.IQuery;
+
+/**
+ * The concrete implementation of {@link IEntity} that is wrapping the design-time representation
+ * of a JPA entity.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+abstract class JpaEntity extends JpaManagedType
+                         implements IEntity {
+
+	/**
+	 * The cached used to quickly retrieve any queries that have been cached.
+	 */
+	private Map<String, IQuery> queries;
+
+	/**
+	 * Creates a new <code>JpaEntity</code>.
+	 *
+	 * @param provider The provider of JPA managed types
+	 * @param entity The design-time model object wrapped by this class
+	 */
+	JpaEntity(JpaManagedTypeProvider provider, Entity entity) {
+		super(provider, entity);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void accept(IManagedTypeVisitor visitor) {
+		visitor.visit(this);
+	}
+
+	final IQuery buildQuery(JpaManagedTypeProvider provider, NamedQuery namedQuery) {
+		return new JpaQuery(provider, namedQuery);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	Entity getManagedType() {
+		return (Entity) super.getManagedType();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public final String getName() {
+		return getManagedType().getName();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IQuery getNamedQuery(String queryName) {
+		initializeQueries();
+		return queries.get(queryName);
+	}
+
+	private void initializeQueries() {
+		if (queries == null) {
+			queries = new HashMap<String, IQuery>();
+			initializeQueries(queries);
+		}
+	}
+
+	void initializeQueries(Map<String, IQuery> queries) {
+		JpaManagedTypeProvider provider = getProvider();
+		for (ListIterator<NamedQuery> iter = namedQueries(); iter.hasNext(); ) {
+			NamedQuery namedQuery = iter.next();
+			queries.put(namedQuery.getName(), buildQuery(provider, namedQuery));
+		}
+	}
+
+	private ListIterator<NamedQuery> namedQueries() {
+		return getManagedType().getQueryContainer().namedQueries();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		return getName();
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaJpqlQueryHelper.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaJpqlQueryHelper.java
new file mode 100644
index 0000000..93ad568
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaJpqlQueryHelper.java
@@ -0,0 +1,245 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import java.util.List;
+import org.eclipse.jpt.common.core.internal.utility.SimpleTextRange;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.jpa.core.context.NamedQuery;
+import org.eclipse.jpt.jpa.core.internal.validation.DefaultJpaValidationMessages;
+import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationMessages;
+import org.eclipse.jpt.jpa.core.internal.validation.JpaValidationPreferences;
+import org.eclipse.persistence.jpa.jpql.ExpressionTools;
+import org.eclipse.persistence.jpa.jpql.JPQLQueryHelper;
+import org.eclipse.persistence.jpa.jpql.JPQLQueryProblem;
+import org.eclipse.persistence.jpa.jpql.spi.IQuery;
+import org.eclipse.wst.validation.internal.provisional.core.IMessage;
+
+/**
+ * This helper can perform the following operations over a JPQL query:
+ * <ul>
+ * <li>Calculates the result type of a query: {@link #getResultType()};</li>
+ * <li>Calculates the type of an input parameter: {@link #getParameterType(String)}.</li>
+ * <li>Calculates the possible choices to complete the query from a given
+ *     position (used for content assist): {@link #buildContentAssistItems(int)}.</li>
+ * <li>Validates the query by introspecting its grammar and semantic:
+ *     <ul>
+ *     <li>{@link #validate()},</li>
+ *     <li>{@link #validateGrammar()},</li>
+ *     <li>{@link #validateSemantic()}.</li>
+ *     </ul></li>
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+@SuppressWarnings("nls")
+public final class JpaJpqlQueryHelper extends JPQLQueryHelper {
+
+	/**
+	 * Caches the provider in order to prevent recreating the SPI representation of the JPA artifacts
+	 * more than once.
+	 */
+	private JpaManagedTypeProvider managedTypeProvider;
+
+	/**
+	 * Creates a new <code>JpaQueryHelper</code>.
+	 */
+	public JpaJpqlQueryHelper() {
+		super();
+	}
+
+	/**
+	 * Calculates the start and end positions by adjusting them to be at the same position within
+	 * <em>jpqlQuery</em>, which may differ from <em>parsedJpqlQuery</em> since the parsed tree does
+	 * not keep track of multiple whitespace. The range is also increased if the start and end
+	 * positions are the same.
+	 *
+	 * @param problem The {@link JPQLQueryProblem problem} that was found in the JPQL query, which is
+	 * either a grammatical or semantic problem
+	 * @param parsedJpqlQuery The string representation of the parsed tree representation of the JPQL
+	 * query
+	 * @param actualQuery The actual JPQL query that was parsed and validated
+	 * @return The start and end positions, which may have been adjusted
+	 */
+	public int[] buildPositions(JPQLQueryProblem problem, String parsedJpqlQuery, String actualQuery) {
+
+		int startPosition = problem.getStartPosition();
+		int endPosition   = problem.getEndPosition();
+
+		// If the start and end positions are the same, then expand the text range
+		if (startPosition == endPosition) {
+			startPosition = Math.max(startPosition - 1, 0);
+		}
+
+		// Reposition the cursor so it's correctly positioned in the actual query, which is the
+		// since it may contains more than one whitespace for a single whitespace
+		int newStartPosition = ExpressionTools.repositionCursor(parsedJpqlQuery, startPosition, actualQuery);
+
+		if (newStartPosition != startPosition) {
+			endPosition  += (newStartPosition - startPosition);
+			startPosition = newStartPosition;
+		}
+
+		return new int[] { startPosition, endPosition };
+	}
+
+	/**
+	 * Creates a new {@link IMessage} for the given {@link JPQLQueryProblem}.
+	 *
+	 * @param namedQuery The model object for which a new {@link IMessage} is creating describing the
+	 * problem
+	 * @param problem The {@link JPQLQueryProblem problem} that was found in the JPQL query, which is
+	 * either a grammatical or semantic problem
+	 * @param textRange The range of the JPQL query in the Java source file
+	 * @param parsedJpqlQuery The string representation of the parsed tree representation of the JPQL
+	 * query, which may differ from the actual JPQL query since it does not keep more than one
+	 * whitespace
+	 * @param actualQuery The actual JPQL query that was parsed and validated
+	 * @param offset This offset is used to move the start position
+	 * @return A new {@link IMessage} that has the required information to display the problem
+	 * underline and the error message in the Problems view
+	 */
+	private IMessage buildProblem(NamedQuery namedQuery,
+	                              TextRange textRange,
+	                              JPQLQueryProblem problem,
+	                              String parsedJpqlQuery,
+	                              String actualQuery,
+	                              int offset) {
+
+		// Convert the positions from the parsed JPQL query to the actual JPQL query
+		int[] positions = buildPositions(problem, parsedJpqlQuery, actualQuery);
+
+		// Now convert the adjusted positions once again to be in the query where the escape
+		// characters are in their literal forms
+		int[] newStartPosition = { positions[0] };
+		ExpressionTools.escape(actualQuery, newStartPosition);
+		int escapeOffset = positions[0] - newStartPosition[0];
+
+		positions[0] -= escapeOffset;
+		positions[1] -= escapeOffset;
+
+		// Create the text range of the problem
+		textRange = new SimpleTextRange(
+			textRange.getOffset() + positions[0] + offset,
+			positions[1] - positions[0],
+			textRange.getLineNumber()
+		);
+
+		// Now create the message
+		IMessage message = DefaultJpaValidationMessages.buildMessage(
+			severity(namedQuery),
+			problem.getMessageKey(),
+			problem.getMessageArguments(),
+			namedQuery,
+			textRange
+		);
+		message.setBundleName("jpa_jpql_validation");
+		return message;
+	}
+
+	private JpaManagedTypeProvider buildProvider(NamedQuery query) {
+		try {
+			return new JpaPersistenceUnit(query.getJpaProject(), query.getPersistenceUnit());
+		}
+		catch (Exception e) {
+			return new JpaMappingFile(query.getJpaProject(), query.getMappingFileRoot().getParent());
+		}
+	}
+
+	/**
+	 * Disposes the provider so the application metadata is not kept in memory.
+	 */
+	public void disposeProvider() {
+		managedTypeProvider = null;
+	}
+
+	/**
+	 * Sets the given named query and string representation of the JPQL query.
+	 *
+	 * @param namedQuery The model object where the JPQL query is stored
+	 * @param actualQuery The actual JPQL query, which can differ from the one owned by the model
+	 * object, which happens when the model is out of sync because it has not been updated yet
+	 */
+	public void setQuery(NamedQuery namedQuery, String actualQuery) {
+
+		if (managedTypeProvider == null) {
+			managedTypeProvider = buildProvider(namedQuery);
+		}
+
+		IQuery query = new JpaQuery(managedTypeProvider, namedQuery, actualQuery);
+		super.setQuery(query);
+	}
+
+	/**
+	 * Retrieve the severity that is associated to JPQL query validation, which cannot be retrieved
+	 * using the JPQL problem message key.
+
+	 * @param targetObject The object for which a new {@link IMessage} is creating describing the
+	 * problem
+	 * @return The global severity for validating JPQL queries
+	 */
+	private int severity(Object targetObject) {
+		return JpaValidationPreferences.getProblemSeverityPreference(
+			targetObject,
+			JpaValidationMessages.JPQL_QUERY_VALIDATION
+		);
+	}
+
+	private boolean shouldValidate(NamedQuery namedQuery) {
+		return JpaValidationPreferences.getProblemSeverityPreference(
+			namedQuery,
+			JpaValidationMessages.JPQL_QUERY_VALIDATION
+		) == -1;
+	}
+
+	/**
+	 * Validates the given {@link NamedQuery} by validating the JPQL query.
+	 *
+	 * @param namedQuery The JPQL query to validate
+	 * @param jpqlQuery The JPQL query, which might be different from what the model object since
+	 * the escape characters should not be in their literal forms (should have '\r' and not '\\r')
+	 * @param textRange The range of the JPQL query string within the document
+	 * @param offset This offset is used to move the start position
+	 * @param messages The list of {@link IMessage IMessages} that will be used to add validation
+	 * problems
+	 */
+	public void validate(NamedQuery namedQuery,
+	                     String jpqlQuery,
+	                     TextRange textRange,
+	                     int offset,
+	                     List<IMessage> messages) {
+
+		// Make this quick check so we don't validate the query, which is time consuming
+		if (shouldValidate(namedQuery)) {
+
+			setQuery(namedQuery, jpqlQuery);
+			String parsedJpqlQuery = getParsedJPQLQuery();
+
+			for (JPQLQueryProblem problem : validate()) {
+
+				IMessage message = buildProblem(
+					namedQuery,
+					textRange,
+					problem,
+					parsedJpqlQuery,
+					jpqlQuery,
+					offset
+				);
+
+				messages.add(message);
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaManagedType.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaManagedType.java
new file mode 100644
index 0000000..a9722d3
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaManagedType.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.eclipse.jpt.jpa.core.context.AttributeMapping;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+import org.eclipse.persistence.jpa.jpql.spi.IManagedType;
+import org.eclipse.persistence.jpa.jpql.spi.IMapping;
+import org.eclipse.persistence.jpa.jpql.spi.IType;
+
+/**
+ * The abstract definition of {@link IManagedType} defined for wrapping the design-time mapped class
+ * object.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+abstract class JpaManagedType implements IManagedType {
+
+	/**
+	 * The design-time model object wrapped by this class.
+	 */
+	private final TypeMapping managedType;
+
+	/**
+	 * The cached collection of {@link IMapping mappings} that prevent rebuilding them every time one
+	 * is requested.
+	 */
+	private Map<String, IMapping> mappings;
+
+	/**
+	 * The provider of JPA managed types.
+	 */
+	private final JpaManagedTypeProvider provider;
+
+	/**
+	 * The cached type of this managed type.
+	 */
+	private IType type;
+
+	/**
+	 * Creates a new <code>JDeveloperManagedType</code>.
+	 *
+	 * @param managedType The provider of JPA managed types
+	 * @param mappedClass The design-time model object wrapped by this class
+	 */
+	JpaManagedType(JpaManagedTypeProvider provider, TypeMapping managedType) {
+		super();
+		this.provider    = provider;
+		this.managedType = managedType;
+	}
+
+	private IMapping buildMapping(AttributeMapping mapping) {
+		return new JpaMapping(this, mapping);
+	}
+
+	private Map<String, IMapping> buildMappings() {
+		Map<String, IMapping> mappings = new HashMap<String, IMapping>();
+		for (Iterator<AttributeMapping> iter = managedType.allAttributeMappings(); iter.hasNext(); ) {
+			AttributeMapping mapping = iter.next();
+			mappings.put(mapping.getName(), buildMapping(mapping));
+		}
+		return mappings;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public int compareTo(IManagedType managedType) {
+		return getType().getName().compareTo(managedType.getType().getName());
+	}
+
+	/**
+	 * Returns the encapsulated model object.
+	 *
+	 * @return The managed type wrapped by this external form
+	 */
+	TypeMapping getManagedType() {
+		return managedType;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public final IMapping getMappingNamed(String name) {
+		initializeMappings();
+		return mappings.get(name);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public final JpaManagedTypeProvider getProvider() {
+		return provider;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public final IType getType() {
+		if (type == null) {
+			type = provider.getTypeRepository().getType(managedType.getPersistentType().getName());
+		}
+		return type;
+	}
+
+	private void initializeMappings() {
+		if (mappings == null) {
+			mappings = buildMappings();
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public final Iterable<IMapping> mappings() {
+		initializeMappings();
+		return Collections.unmodifiableCollection(mappings.values());
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaManagedTypeProvider.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaManagedTypeProvider.java
new file mode 100644
index 0000000..e42748c
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaManagedTypeProvider.java
@@ -0,0 +1,277 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.eclipse.jpt.jpa.core.JpaFacet;
+import org.eclipse.jpt.jpa.core.JpaPlatform;
+import org.eclipse.jpt.jpa.core.JpaProject;
+import org.eclipse.jpt.jpa.core.context.Embeddable;
+import org.eclipse.jpt.jpa.core.context.Entity;
+import org.eclipse.jpt.jpa.core.context.MappedSuperclass;
+import org.eclipse.jpt.jpa.core.context.PersistentType;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+import org.eclipse.jpt.jpa.core.context.persistence.PersistentTypeContainer;
+import org.eclipse.jpt.jpa.core.internal.jpa1.GenericJpaProject;
+import org.eclipse.persistence.jpa.jpql.spi.IEmbeddable;
+import org.eclipse.persistence.jpa.jpql.spi.IEntity;
+import org.eclipse.persistence.jpa.jpql.spi.IJPAVersion;
+import org.eclipse.persistence.jpa.jpql.spi.IManagedType;
+import org.eclipse.persistence.jpa.jpql.spi.IManagedTypeProvider;
+import org.eclipse.persistence.jpa.jpql.spi.IManagedTypeVisitor;
+import org.eclipse.persistence.jpa.jpql.spi.IMappedSuperclass;
+import org.eclipse.persistence.jpa.jpql.spi.IPlatform;
+import org.eclipse.persistence.jpa.jpql.spi.IType;
+
+/**
+ * The abstract implementation of {@link IManagedTypeProvider} that is wrapping the design-time
+ * representation of a provider of managed types.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+abstract class JpaManagedTypeProvider implements IManagedTypeProvider {
+
+	/**
+	 * The filtered collection of managed types that are the abstract schema types.
+	 */
+	private Collection<IEntity> abstractSchemaTypes;
+
+	/**
+	 * The project that gives access to the application's metadata.
+	 */
+	private final JpaProject jpaProject;
+
+	/**
+	 * The cached {@link IManagedType managed types}.
+	 */
+	private Map<String, IManagedType> managedTypes;
+
+	/**
+	 * The design-time provider of managed types.
+	 */
+	private final PersistentTypeContainer persistentTypeContainer;
+
+	/**
+	 * The external form of a type repository.
+	 */
+	private JpaTypeRepository typeRepository;
+
+	/**
+	 * The version of the Java Persistence this entity for which it was defined.
+	 */
+	private IJPAVersion version;
+
+	/**
+	 * Creates a new <code>JpaManagedTypeProvider</code>.
+	 *
+	 * @param jpaProject The project that gives access to the application's metadata
+	 * @param persistentTypeContainer The design-time provider of managed types
+	 */
+	JpaManagedTypeProvider(JpaProject jpaProject, PersistentTypeContainer persistentTypeContainer) {
+
+		super();
+		this.jpaProject = jpaProject;
+		this.persistentTypeContainer = persistentTypeContainer;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Iterable<IEntity> abstractSchemaTypes() {
+		if (abstractSchemaTypes == null) {
+			initializeManagedTypes();
+			EntityCollector visitor = new EntityCollector();
+			for (IManagedType managedType : managedTypes.values()) {
+				managedType.accept(visitor);
+			}
+			abstractSchemaTypes = visitor.entities;
+		}
+		return Collections.unmodifiableCollection(abstractSchemaTypes);
+	}
+
+	abstract JpaEntity buildEntity(TypeMapping mappedClass);
+
+	private IManagedType buildManagedType(PersistentType persistentType) {
+
+		TypeMapping mappedClass = persistentType.getMapping();
+
+		if (mappedClass instanceof Entity) {
+			return buildEntity(mappedClass);
+		}
+
+		if (mappedClass instanceof MappedSuperclass) {
+			return new JpaMappedSuperclass(this, (MappedSuperclass) mappedClass);
+		}
+
+		if (mappedClass instanceof Embeddable) {
+			return new JpaEmbeddable(this, (Embeddable) mappedClass);
+		}
+
+		return new JpaNullManagedType(this, mappedClass);
+	}
+
+	private Map<String, IManagedType> buildManagedTypes() {
+		Map<String, IManagedType> managedTypes = new HashMap<String, IManagedType>();
+		for (Iterator<? extends PersistentType> iter = persistenceTypes(); iter.hasNext(); ) {
+			PersistentType persistentType = iter.next();
+			if (persistentType != null) {
+				managedTypes.put(persistentType.getMapping().getName(), buildManagedType(persistentType));
+			}
+		}
+		return managedTypes;
+	}
+
+	private IJPAVersion convert(JpaPlatform.Version version) {
+
+		String jpaVersion = version.getJpaVersion();
+
+		if (JpaFacet.VERSION_1_0.getVersionString().equals(jpaVersion)) {
+			return IJPAVersion.VERSION_1_0;
+		}
+
+		return IJPAVersion.VERSION_2_0;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IManagedType getManagedType(IType type) {
+
+		initializeManagedTypes();
+
+		for (IManagedType managedType : managedTypes.values()) {
+			if (managedType.getType() == type) {
+				return managedType;
+			}
+		}
+
+		return null;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IManagedType getManagedType(String abstractSchemaName) {
+		initializeManagedTypes();
+		return managedTypes.get(abstractSchemaName);
+	}
+
+	/**
+	 * Returns the container of managed types.
+	 *
+	 * @return The container of managed types
+	 */
+	PersistentTypeContainer getPersistentTypeContainer() {
+		return persistentTypeContainer;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IPlatform getPlatform() {
+		return (jpaProject instanceof GenericJpaProject) ? IPlatform.JAVA  : IPlatform.ECLIPSE_LINK;
+	}
+
+	/**
+	 * Returns the encapsulated {@link PersistentType}, which is the actual object.
+	 *
+	 * @return The design-time representation of a managed type provider
+	 */
+	PersistentTypeContainer getProvider() {
+		return persistentTypeContainer;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public JpaTypeRepository getTypeRepository() {
+		if (typeRepository == null) {
+			typeRepository = new JpaTypeRepository(jpaProject.getJavaProject());
+		}
+		return typeRepository;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IJPAVersion getVersion() {
+		if (version == null) {
+			version = convert(jpaProject.getJpaPlatform().getJpaVersion());
+		}
+		return version;
+	}
+
+	private void initializeManagedTypes() {
+		if (managedTypes == null) {
+			managedTypes = buildManagedTypes();
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Iterable<IManagedType> managedTypes() {
+		initializeManagedTypes();
+		return Collections.unmodifiableCollection(managedTypes.values());
+	}
+
+	/**
+	 * Retrieves the managed types from the design-time provider.
+	 *
+	 * @return The managed types that are defined only in the provider
+	 */
+	abstract Iterator<? extends PersistentType> persistenceTypes();
+
+	private static class EntityCollector implements IManagedTypeVisitor {
+
+		/**
+		 * The collection of {@link IEntity entities} that got visited.
+		 */
+		private final Collection<IEntity> entities;
+
+		/**
+		 * Creates a new <code>EntityCollector</code>.
+		 */
+		EntityCollector() {
+			super();
+			entities = new ArrayList<IEntity>();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public void visit(IEmbeddable embeddable) {
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public void visit(IEntity entity) {
+			entities.add(entity);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public void visit(IMappedSuperclass mappedSuperclass) {
+		}
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaMappedSuperclass.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaMappedSuperclass.java
new file mode 100644
index 0000000..3f40e32
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaMappedSuperclass.java
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import org.eclipse.jpt.jpa.core.context.MappedSuperclass;
+import org.eclipse.persistence.jpa.jpql.spi.IManagedTypeVisitor;
+import org.eclipse.persistence.jpa.jpql.spi.IMappedSuperclass;
+
+/**
+ * The concrete implementation of {@link IMappedSuperclass} that is wrapping the design-time
+ * representation of a JPA mapped superclass.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+final class JpaMappedSuperclass extends JpaManagedType
+                                implements IMappedSuperclass {
+
+	/**
+	 * Creates a new <code>JpaMappedSuperclass</code>.
+	 *
+	 * @param provider The provider of JPA managed types
+	 * @param mappedSuperclass The design-time model object wrapped by this class
+	 */
+	JpaMappedSuperclass(JpaManagedTypeProvider provider, MappedSuperclass mappedSuperclass) {
+		super(provider, mappedSuperclass);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void accept(IManagedTypeVisitor visitor) {
+		visitor.visit(this);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	MappedSuperclass getManagedType() {
+		return (MappedSuperclass) super.getManagedType();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		return getType().getName();
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaMapping.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaMapping.java
new file mode 100644
index 0000000..faebd4d
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaMapping.java
@@ -0,0 +1,270 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import java.lang.annotation.Annotation;
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.jpt.common.utility.internal.CollectionTools;
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.jpt.common.utility.internal.iterators.TransformationIterator;
+import org.eclipse.jpt.jpa.core.MappingKeys;
+import org.eclipse.jpt.jpa.core.context.AttributeMapping;
+import org.eclipse.jpt.jpa.core.context.PersistentAttribute;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentAttribute;
+import org.eclipse.jpt.jpa.core.jpa2.MappingKeys2_0;
+import org.eclipse.jpt.jpa.core.resource.java.JavaResourcePersistentAttribute;
+import org.eclipse.persistence.jpa.jpql.spi.IManagedType;
+import org.eclipse.persistence.jpa.jpql.spi.IMapping;
+import org.eclipse.persistence.jpa.jpql.spi.IMappingType;
+import org.eclipse.persistence.jpa.jpql.spi.IType;
+import org.eclipse.persistence.jpa.jpql.spi.ITypeDeclaration;
+
+/**
+ * The concrete implementation of {@link IMapping} that is wrapping the design-time representation
+ * of a mapping.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+@SuppressWarnings("nls")
+final class JpaMapping implements IMapping {
+
+	/**
+	 * The design-time {@link AttributeMapping} wrapped by this class.
+	 */
+	private final AttributeMapping mapping;
+
+	/**
+	 * The type of the actual mapping.
+	 */
+	private IMappingType mappingType;
+
+	/**
+	 * The parent of this mapping.
+	 */
+	private final JpaManagedType parent;
+
+	/**
+	 * The {@link IType} of the property represented by the mapping.
+	 */
+	private IType type;
+
+	/**
+	 * The {@link ITypeDeclaration} of the property represented by the mapping.
+	 */
+	private ITypeDeclaration typeDeclaration;
+
+	/**
+	 * Creates a new <code>JpaMapping</code>.
+	 *
+	 * @param parent The parent of this mapping
+	 * @param mapping The design-time {@link AttributeMapping} wrapped by this class
+	 */
+	JpaMapping(JpaManagedType parent, AttributeMapping mapping) {
+		super();
+		this.parent  = parent;
+		this.mapping = mapping;
+	}
+
+	private ITypeDeclaration[] buildGenericTypeDeclarations() {
+		JavaPersistentAttribute javaPersistentAttribute = mapping.getPersistentAttribute().getJavaPersistentAttribute();
+		JavaResourcePersistentAttribute resource = javaPersistentAttribute.getResourcePersistentAttribute();
+		List<ITypeDeclaration> declarations = CollectionTools.list(buildGenericTypeDeclarations(resource));
+		return declarations.toArray(new ITypeDeclaration[declarations.size()]);
+	}
+
+	private Iterator<ITypeDeclaration> buildGenericTypeDeclarations(JavaResourcePersistentAttribute resource) {
+		return new TransformationIterator<String, ITypeDeclaration>(resource.typeTypeArgumentNames()) {
+			@Override
+			protected ITypeDeclaration transform(String next) {
+				return getTypeRepository().getType(next).getTypeDeclaration();
+			}
+		};
+	}
+
+	private ITypeDeclaration buildTypeDeclaration() {
+
+		PersistentAttribute property = mapping.getPersistentAttribute();
+		boolean array = property.getTypeName().endsWith("[]");
+		int dimensionality = 0;
+
+		if (array) {
+			dimensionality = getType().getTypeDeclaration().getDimensionality();
+		}
+
+		return new JpaTypeDeclaration(
+			getType(),
+			buildGenericTypeDeclarations(),
+			dimensionality
+		);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public int compareTo(IMapping mapping) {
+		return getName().compareTo(mapping.getName());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IMappingType getMappingType() {
+		if (mappingType == null) {
+			getTypeDeclaration();
+			mappingType = mappingType();
+		}
+		return mappingType;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String getName() {
+		return mapping.getName();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IManagedType getParent() {
+		return parent;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IType getType() {
+		if (type == null) {
+			PersistentAttribute property = mapping.getPersistentAttribute();
+			type = getTypeRepository().getType(property.getTypeName());
+		}
+		return type;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public ITypeDeclaration getTypeDeclaration() {
+		if (typeDeclaration == null) {
+			typeDeclaration = buildTypeDeclaration();
+		}
+		return typeDeclaration;
+	}
+
+	private JpaTypeRepository getTypeRepository() {
+		return parent.getProvider().getTypeRepository();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean hasAnnotation(Class<? extends Annotation> annotationType) {
+		JavaResourcePersistentAttribute attribute = mapping.getPersistentAttribute().getJavaPersistentAttribute().getResourcePersistentAttribute();
+		return attribute.getAnnotation(annotationType.getName()) != null;
+	}
+
+	private IMappingType mappingType() {
+
+		String type = mapping.getKey();
+
+		// Basic
+		if (type == MappingKeys.BASIC_ATTRIBUTE_MAPPING_KEY) {
+			return IMappingType.BASIC;
+		}
+
+		// Embedded
+		if (type == MappingKeys.EMBEDDED_ATTRIBUTE_MAPPING_KEY) {
+			return IMappingType.EMBEDDED;
+		}
+
+		// Embedded Id
+		if (type == MappingKeys.EMBEDDED_ID_ATTRIBUTE_MAPPING_KEY) {
+			return IMappingType.EMBEDDED_ID;
+		}
+
+		// Id
+		if (type == MappingKeys.ID_ATTRIBUTE_MAPPING_KEY) {
+			return IMappingType.ID;
+		}
+
+		// M:M
+		if (type == MappingKeys.MANY_TO_MANY_ATTRIBUTE_MAPPING_KEY) {
+			return IMappingType.MANY_TO_MANY;
+		}
+
+		// 1:M
+		if (type == MappingKeys.ONE_TO_MANY_ATTRIBUTE_MAPPING_KEY) {
+			return IMappingType.ONE_TO_MANY;
+		}
+
+		// M:1
+		if (type == MappingKeys.MANY_TO_ONE_ATTRIBUTE_MAPPING_KEY) {
+			return IMappingType.MANY_TO_ONE;
+		}
+
+		// 1:1
+		if (type == MappingKeys.ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY) {
+			return IMappingType.ONE_TO_ONE;
+		}
+
+		// Version
+		if (type == MappingKeys.VERSION_ATTRIBUTE_MAPPING_KEY) {
+			return IMappingType.VERSION;
+		}
+
+		// Element Collection
+		if (type == MappingKeys2_0.ELEMENT_COLLECTION_ATTRIBUTE_MAPPING_KEY) {
+			return IMappingType.ELEMENT_COLLECTION;
+		}
+
+		// Basic Collection
+//		if (type == EclipseLinkMappingKeys.BASIC_COLLECTION_ATTRIBUTE_MAPPING_KEY) {
+//			return IMappingType.BASIC_COLLECTION;
+//		}
+//
+//		// Basic Map
+//		if (type == EclipseLinkMappingKeys.BASIC_MAP_ATTRIBUTE_MAPPING_KEY) {
+//			return IMappingType.BASIC_MAP;
+//		}
+//
+//		// Transformation
+//		if (type == EclipseLinkMappingKeys.TRANSFORMATION_ATTRIBUTE_MAPPING_KEY) {
+//			return IMappingType.TRANSFORMATION;
+//		}
+//
+//		// Variable 1:1
+//		if (type == EclipseLinkMappingKeys.VARIABLE_ONE_TO_ONE_ATTRIBUTE_MAPPING_KEY) {
+//			return IMappingType.VARIABLE_ONE_TO_ONE;
+//		}
+
+		return IMappingType.TRANSIENT;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		StringTools.buildSimpleToStringOn(this, sb);
+		sb.append(", name=");
+		sb.append(getName());
+		sb.append(", mappingType=");
+		sb.append(getMappingType());
+		return sb.toString();
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaMappingFile.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaMappingFile.java
new file mode 100644
index 0000000..d3b2a08
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaMappingFile.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the 
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
+ * which accompanies this distribution. 
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at 
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import java.util.Iterator;
+import org.eclipse.jpt.jpa.core.JpaProject;
+import org.eclipse.jpt.jpa.core.context.Entity;
+import org.eclipse.jpt.jpa.core.context.MappingFile;
+import org.eclipse.jpt.jpa.core.context.PersistentType;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+
+/**
+ * The concrete implementation that is wrapping the design-time representation of a mapping file.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+public class JpaMappingFile extends JpaManagedTypeProvider {
+
+	/**
+	 * Creates a new <code>JpaMappingFile</code>.
+	 * 
+	 * @param jpaProject The project that gives access to the application's metadata
+	 * @param persistentTypeContainer The design-time provider of managed types
+	 */
+	public JpaMappingFile(JpaProject jpaProject, MappingFile persistentTypeContainer) {
+		super(jpaProject, persistentTypeContainer);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	JpaEntity buildEntity(TypeMapping mappedClass) {
+		return new JpaOrmEntity(this, (Entity) mappedClass);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	protected MappingFile getPersistentTypeContainer() {
+		return (MappingFile) super.getPersistentTypeContainer();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	protected Iterator<? extends PersistentType> persistenceTypes() {
+		return getPersistentTypeContainer().getPersistentTypes().iterator();
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaNullManagedType.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaNullManagedType.java
new file mode 100644
index 0000000..fcb6384
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaNullManagedType.java
@@ -0,0 +1,112 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+import org.eclipse.persistence.jpa.jpql.spi.IManagedType;
+import org.eclipse.persistence.jpa.jpql.spi.IManagedTypeProvider;
+import org.eclipse.persistence.jpa.jpql.spi.IManagedTypeVisitor;
+import org.eclipse.persistence.jpa.jpql.spi.IMapping;
+import org.eclipse.persistence.jpa.jpql.spi.IType;
+
+/**
+ * The concrete implementation of {@link IManagedType} that is wrapping the design-time
+ * representation a "null" managed type.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+final class JpaNullManagedType implements IManagedType {
+
+	/**
+	 * The provider of JPA managed types.
+	 */
+	private final JpaManagedTypeProvider provider;
+
+	/**
+	 * The cached {@link IType} of this "null" managed type.
+	 */
+	private IType type;
+
+	/**
+	 * The design-time model object wrapped by this class.
+	 */
+	private final TypeMapping typeMapping;
+
+	/**
+	 * Creates a new <code>JpaNullManagedType</code>.
+	 *
+	 * @param managedType The provider of JPA managed types
+	 * @param typeMapping The design-time model object wrapped by this class
+	 */
+	JpaNullManagedType(JpaManagedTypeProvider provider, TypeMapping typeMapping) {
+		super();
+		this.provider    = provider;
+		this.typeMapping = typeMapping;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void accept(IManagedTypeVisitor visitor) {
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public int compareTo(IManagedType managedType) {
+		return getType().getName().compareTo(managedType.getType().getName());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IMapping getMappingNamed(String name) {
+		return null;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IManagedTypeProvider getProvider() {
+		return provider;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IType getType() {
+		if (type == null) {
+			type = provider.getTypeRepository().getType(typeMapping.getPersistentType().getName());
+		}
+		return type;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Iterable<IMapping> mappings() {
+		return EmptyIterable.instance();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		return getType().getName();
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaOrmEntity.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaOrmEntity.java
new file mode 100644
index 0000000..03eb192
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaOrmEntity.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import java.util.ListIterator;
+import java.util.Map;
+import org.eclipse.jpt.jpa.core.context.Entity;
+import org.eclipse.jpt.jpa.core.context.NamedQuery;
+import org.eclipse.jpt.jpa.core.context.java.JavaTypeMapping;
+import org.eclipse.jpt.jpa.core.context.orm.OrmPersistentType;
+import org.eclipse.persistence.jpa.jpql.spi.IQuery;
+
+/**
+ * The concrete implementation of {@link IEntity} that is wrapping the design-time representation
+ * of a JPA entity defined in an ORM configuration.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+final class JpaOrmEntity extends JpaEntity {
+
+	/**
+	 * Creates a new <code>JpaOrmEntity</code>.
+	 *
+	 * @param provider The provider of JPA managed types
+	 * @param entity The design-time model object wrapped by this class
+	 */
+	JpaOrmEntity(JpaMappingFile provider, Entity entity) {
+		super(provider, entity);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	void initializeQueries(Map<String, IQuery> queries) {
+		super.initializeQueries(queries);
+
+		JpaManagedTypeProvider provider = getProvider();
+		OrmPersistentType type = (OrmPersistentType) getManagedType().getPersistentType();
+		JavaTypeMapping mapping = type.getJavaPersistentType().getMapping();
+
+		if (mapping instanceof Entity) {
+			Entity entity = (Entity) mapping;
+			for (ListIterator<NamedQuery> iter = entity.getQueryContainer().namedQueries(); iter.hasNext(); ) {
+				NamedQuery namedQuery = iter.next();
+				queries.put(namedQuery.getName(), buildQuery(provider, namedQuery));
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaPersistenceUnit.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaPersistenceUnit.java
new file mode 100644
index 0000000..c6b289b
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaPersistenceUnit.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the 
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
+ * which accompanies this distribution. 
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at 
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import java.util.Iterator;
+import org.eclipse.jpt.common.utility.internal.iterators.CompositeIterator;
+import org.eclipse.jpt.common.utility.internal.iterators.TransformationIterator;
+import org.eclipse.jpt.jpa.core.JpaProject;
+import org.eclipse.jpt.jpa.core.context.Entity;
+import org.eclipse.jpt.jpa.core.context.PersistentType;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+import org.eclipse.jpt.jpa.core.context.persistence.ClassRef;
+import org.eclipse.jpt.jpa.core.context.persistence.PersistenceUnit;
+
+/**
+ * The concrete implementation that is wrapping the design-time representation of a persistence unit.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+public final class JpaPersistenceUnit extends JpaManagedTypeProvider {
+
+	/**
+	 * Creates a new <code>JpaPersistenceUnit</code>.
+	 *
+	 * @param jpaProject The project that gives access to the application's metadata
+	 * @param persistentUnit The design-time persistence unit
+	 */
+	public JpaPersistenceUnit(JpaProject jpaProject, PersistenceUnit persistentUnit) {
+		super(jpaProject, persistentUnit);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	JpaEntity buildEntity(TypeMapping mappedClass) {
+		return new JpaPersistenceUnitEntity(this, (Entity) mappedClass);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	PersistenceUnit getPersistentTypeContainer() {
+		return (PersistenceUnit) super.getPersistentTypeContainer();
+	}
+
+	@SuppressWarnings("unchecked")
+	private Iterator<ClassRef> javaClassRefs() {
+		return new CompositeIterator<ClassRef>(
+			getPersistentTypeContainer().specifiedClassRefs(),
+			getPersistentTypeContainer().impliedClassRefs()
+		);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	Iterator<? extends PersistentType> persistenceTypes() {
+		return new TransformationIterator<ClassRef, PersistentType>(javaClassRefs()) {
+			@Override
+			protected PersistentType transform(ClassRef classRef) {
+				return classRef.getJavaPersistentType();
+			}
+		};
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaPersistenceUnitEntity.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaPersistenceUnitEntity.java
new file mode 100644
index 0000000..c552d87
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaPersistenceUnitEntity.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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.
+ * 
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import org.eclipse.jpt.jpa.core.context.Entity;
+
+/**
+ * The concrete implementation of {@link IEntity} that is wrapping the design-time representation
+ * of a JPA entity defined in a persistence unit.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+final class JpaPersistenceUnitEntity extends JpaEntity {
+
+	/**
+	 * Creates a new <code>JpaPersistenceUnitEntity</code>.
+	 *
+	 * @param provider The provider of JPA managed types
+	 * @param entity The design-time model object wrapped by this class
+	 */
+	JpaPersistenceUnitEntity(JpaManagedTypeProvider provider, Entity entity) {
+		super(provider, entity);
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaQuery.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaQuery.java
new file mode 100644
index 0000000..45d4f2f
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaQuery.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the 
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 
+ * which accompanies this distribution. 
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at 
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.jpt.jpa.core.context.NamedQuery;
+import org.eclipse.persistence.jpa.jpql.spi.IQuery;
+
+/**
+ * The concrete implementation of {@link IQuery} that is wrapping the design-time representation
+ * of a JPQL query.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+@SuppressWarnings("nls")
+public final class JpaQuery implements IQuery {
+
+	/**
+	 * The actual JPQL query, which can differ from the one owned by the model object, which happens
+	 * when the model is out of sync because it has not been updated yet.
+	 */
+	private String actualQuery;
+
+	/**
+	 *  The provider of managed types.
+	 */
+	private JpaManagedTypeProvider provider;
+
+	/**
+	 * The model object holding onto the JPQL query.
+	 */
+	private NamedQuery query;
+
+	/**
+	 * Creates a new <code>JpaQuery</code>.
+	 *
+	 * @param provider The provider of managed types
+	 * @param query The model object of the JPQL query
+	 */
+	public JpaQuery(JpaManagedTypeProvider provider, NamedQuery query) {
+		this(provider, query, query.getQuery());
+	}
+
+	/**
+	 * Creates a new <code>JpaQuery</code>.
+	 *
+	 * @param provider The provider of managed types
+	 * @param query The model object of the JPQL query
+	 * @param actualQuery The actual JPQL query, which can differ from the one owned by the model
+	 * object, which happens when the model is out of sync because it has not been updated yet
+	 */
+	JpaQuery(JpaManagedTypeProvider provider, NamedQuery query, String actualQuery) {
+		super();
+		initialize(provider, query, actualQuery);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String getExpression() {
+		return actualQuery;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public JpaManagedTypeProvider getProvider() {
+		return provider;
+	}
+
+	/**
+	 * Returns the encapsulated {@link NamedQuery}, which is the actual object.
+	 *
+	 * @return The design-time representation of a JPQL query
+	 */
+	NamedQuery getQuery() {
+		return query;
+	}
+
+	private void initialize(JpaManagedTypeProvider provider, NamedQuery query, String actualQuery) {
+
+		this.query       = query;
+		this.provider    = provider;
+		this.actualQuery = actualQuery;
+
+		if (this.actualQuery == null) {
+			this.actualQuery = StringTools.EMPTY_STRING;
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		sb.append(super.toString());
+		sb.append(", query=");
+		sb.append(getExpression());
+		return sb.toString();
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaType.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaType.java
new file mode 100644
index 0000000..3e12d02
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaType.java
@@ -0,0 +1,430 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import java.lang.annotation.Annotation;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.jdt.core.Flags;
+import org.eclipse.jdt.core.IField;
+import org.eclipse.jdt.core.IJavaElement;
+import org.eclipse.jdt.core.IMember;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.ITypeHierarchy;
+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.AbstractTypeDeclaration;
+import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
+import org.eclipse.jdt.core.dom.ClassInstanceCreation;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
+import org.eclipse.jdt.core.dom.IMethodBinding;
+import org.eclipse.jdt.core.dom.ITypeBinding;
+import org.eclipse.jdt.core.dom.NodeFinder;
+import org.eclipse.jpt.common.core.internal.utility.jdt.ASTTools;
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.jpt.jpa.core.JptJpaCorePlugin;
+import org.eclipse.persistence.jpa.jpql.ExpressionTools;
+import org.eclipse.persistence.jpa.jpql.spi.IConstructor;
+import org.eclipse.persistence.jpa.jpql.spi.ITypeDeclaration;
+
+/**
+ * The concrete implementation of {@link org.eclipse.persistence.jpa.query.spi.IType IType} that is
+ * wrapping the design-time representation of a Java type.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+final class JpaType implements IJpaType {
+
+	/**
+	 * The cached collection of {@link IConstructor constructors}.
+	 */
+	private Collection<IConstructor> constructors;
+
+	/**
+	 * The list of names for the {@link Enum}'s constants otherwise an empty array.
+	 */
+	private String[] enumConstants;
+
+	/**
+	 * The design-time representation of a Java type.
+	 */
+	private IType type;
+
+	/**
+	 * The {@link ITypeBinding} for the type, which is the information that was resolved and which
+	 * can be used to query information about that type.
+	 */
+	private ITypeBinding typeBinding;
+
+	/**
+	 * This flag makes sure to not try more than once resolving the {@link ITypeBinding} if it fails
+	 * the first time.
+	 */
+	private boolean typeBindingResolved;
+
+	/**
+	 * Caches the type hierarchy of the {@link IType} in order to prevent rebuilding it each time.
+	 */
+	private ITypeDeclaration typeDeclaration;
+
+	/**
+	 * Caches the type hierarchy of the {@link IType} in order to prevent rebuilding it each time
+	 * {@link #isAssignableTo(org.eclipse.persistence.jpa.query.spi.IType)} is called.
+	 */
+	private ITypeHierarchy typeHierarchy;
+
+	/**
+	 * The fully qualified name of the Java type.
+	 */
+	private final String typeName;
+
+	/**
+	 * The external form of a type repository.
+	 */
+	private final JpaTypeRepository typeRepository;
+
+	/**
+	 * Creates a new <code>JpaType</code>.
+	 *
+	 * @param typeRepository The external form of a type repository
+	 * @param type The design-time representation of a Java type
+	 */
+	JpaType(JpaTypeRepository typeRepository, IType type) {
+		super();
+		this.type           = type;
+		this.typeName       = type.getFullyQualifiedName();
+		this.typeRepository = typeRepository;
+	}
+
+	private CompilationUnit buildCompilationUnit() {
+
+		ASTParser parser = ASTParser.newParser(AST.JLS3);
+		parser.setSource(type.getTypeRoot());
+		parser.setIgnoreMethodBodies(true);
+		parser.setResolveBindings(true);
+		parser.setBindingsRecovery(true);
+
+		return (CompilationUnit) parser.createAST(new NullProgressMonitor());
+	}
+
+	private Collection<IConstructor> buildConstructors() {
+
+		ITypeBinding typeBinding = getTypeBinding();
+
+		// No Java source is attached to the Java class file, parse the class with a reader
+		if ((typeBinding == null) && type.isBinary()) {
+			Collection<IConstructor> constructors = new ArrayList<IConstructor>();
+
+			try {
+				// Root types
+				for (IJavaElement rootType : type.getTypeRoot().getChildren()) {
+					// Root type
+					if (rootType.getElementType() == IJavaElement.TYPE) {
+						for (IJavaElement javaElement : ((IType) rootType).getChildren()) {
+							// Method
+							if (javaElement.getElementType() == IJavaElement.METHOD) {
+								IMethod method = (IMethod) javaElement;
+								// Constructor
+								if (method.isConstructor()) {
+									constructors.add(new ClassConstructor(this, method));
+								}
+							}
+						}
+					}
+				}
+			}
+			catch (Exception e) {
+				JptJpaCorePlugin.log(e);
+			}
+
+			return constructors;
+		}
+		// Use the ITypeBinding to retrieve the constructors
+		else if (typeBinding != null) {
+			Collection<IConstructor> constructors = new ArrayList<IConstructor>();
+
+			for (IMethodBinding method : typeBinding.getDeclaredMethods()) {
+				if (method.isConstructor()) {
+					constructors.add(new JpaConstructor(this, method));
+				}
+			}
+
+			return constructors;
+		}
+
+		return Collections.emptyList();
+	}
+
+	private String[] buildEnumConstants() {
+
+		try {
+			// Retrieve the enum constants from IType
+			if (type.isEnum()) {
+				List<String> names = new ArrayList<String>();
+
+				for (IField field : type.getFields()) {
+					if (field.isEnumConstant()) {
+						names.add(field.getElementName());
+					}
+				}
+
+				return names.toArray(new String[names.size()]);
+			}
+		}
+		catch (Exception e) {
+			// Just ignore and return an empty array
+		}
+
+		return ExpressionTools.EMPTY_STRING_ARRAY;
+	}
+
+	private ITypeBinding buildTypeBinding() {
+
+		// This code was copied from ASTNodes.getTypeBinding(CompilationUnit, IType)
+		try {
+			CompilationUnit compilationUnit = buildCompilationUnit();
+
+			if (type.isAnonymous()) {
+				IJavaElement parent = type.getParent();
+
+				if ((parent instanceof IField) && Flags.isEnum(((IMember) parent).getFlags())) {
+					ASTNode node = NodeFinder.perform(compilationUnit, type.getNameRange());
+					EnumConstantDeclaration constant = (EnumConstantDeclaration) node;
+
+					if (constant != null) {
+						AnonymousClassDeclaration declaration = constant.getAnonymousClassDeclaration();
+
+						if (declaration != null) {
+							return declaration.resolveBinding();
+						}
+					}
+				}
+				else {
+					ASTNode node = NodeFinder.perform(compilationUnit, type.getNameRange());
+					ClassInstanceCreation creation = (ClassInstanceCreation) getParent(node, ClassInstanceCreation.class);
+
+					if (creation != null) {
+						return creation.resolveTypeBinding();
+					}
+				}
+			}
+			else {
+				ASTNode node = NodeFinder.perform(compilationUnit, type.getNameRange());
+				AbstractTypeDeclaration declaration = (AbstractTypeDeclaration) getParent(node, AbstractTypeDeclaration.class);
+
+				if (declaration != null) {
+					return declaration.resolveBinding();
+				}
+			}
+		}
+		catch (Exception e) {
+			// Simply ignore
+		}
+
+		return null;
+	}
+
+	private ITypeDeclaration buildTypeDeclaration() {
+		return new JpaTypeDeclaration(this, new ITypeDeclaration[0]);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Iterable<IConstructor> constructors() {
+		if (constructors == null) {
+			constructors = buildConstructors();
+		}
+		return constructors;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean equals(Object object) {
+		return (this == object) || equals((org.eclipse.persistence.jpa.jpql.spi.IType) object);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean equals(org.eclipse.persistence.jpa.jpql.spi.IType type) {
+		return (this == type) || typeName.equals(type.getName());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String[] getEnumConstants() {
+		if (enumConstants == null) {
+			enumConstants = buildEnumConstants();
+		}
+		return enumConstants;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String getName() {
+		return typeName;
+	}
+
+	private ASTNode getParent(ASTNode node, Class<? extends ASTNode> parentClass) {
+
+		do {
+			node = node.getParent();
+		}
+		while ((node != null) && !parentClass.isInstance(node));
+
+		return node;
+	}
+
+	/**
+	 * Returns the encapsulated {@link Type}, which is the actual type.
+	 *
+	 * @return The design-time representation of a Java type
+	 */
+	IType getType() {
+		return type;
+	}
+
+	private ITypeBinding getTypeBinding() {
+		if ((typeBinding == null) && !typeBindingResolved) {
+			typeBinding = buildTypeBinding();
+			typeBindingResolved = true;
+		}
+		return typeBinding;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public ITypeDeclaration getTypeDeclaration() {
+		if (typeDeclaration == null) {
+			typeDeclaration = buildTypeDeclaration();
+		}
+		return typeDeclaration;
+	}
+
+	/**
+	 * Returns the repository that gives access to the application's classes.
+	 *
+	 * @return The external form of the type repository
+	 */
+	JpaTypeRepository getTypeRepository() {
+		return typeRepository;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean hasAnnotation(Class<? extends Annotation> annotationType) {
+		return type.getAnnotation(annotationType.getName()) != null;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public int hashCode() {
+		return typeName.hashCode();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isAssignableTo(org.eclipse.persistence.jpa.jpql.spi.IType otherType) {
+
+		if (this == otherType) {
+			return true;
+		}
+
+		String otherTypeName = otherType.getName();
+
+		// Type hierarchy for Java compiled classes
+		ITypeBinding typeBinding = getTypeBinding();
+
+		// Type hierarchy for Class files
+		if ((typeBinding == null) && type.isBinary()) {
+
+			// First create the type hierarchy
+			if (typeHierarchy == null) {
+				try {
+					typeHierarchy = type.newSupertypeHierarchy(new NullProgressMonitor());
+				}
+				catch (Exception e) {
+					return false;
+				}
+			}
+
+			// Now check if the other type name is in the type hierarchy
+			for (IType superType : typeHierarchy.getAllTypes()) {
+				if (superType.getFullyQualifiedName().equals(otherTypeName)) {
+					return true;
+				}
+			}
+		}
+		// Type hierarchy for Java source files
+		else if (typeBinding != null) {
+			return ASTTools.typeIsSubTypeOf(typeBinding, otherTypeName);
+		}
+
+		// Anything else is always false
+		return false;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isEnum() {
+		try {
+			return type.isEnum();
+		}
+		catch (Exception e) {
+			// Simply ignore and return no
+			return false;
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isResolvable() {
+		return true;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void setTypeDeclaration(JpaTypeDeclaration typeDeclaration) {
+		this.typeDeclaration = typeDeclaration;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		return StringTools.buildToStringFor(this, typeName);
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaTypeDeclaration.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaTypeDeclaration.java
new file mode 100644
index 0000000..7927bb9
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaTypeDeclaration.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import org.eclipse.persistence.jpa.jpql.spi.IType;
+import org.eclipse.persistence.jpa.jpql.spi.ITypeDeclaration;
+
+/**
+ * The concrete implementation of {@link ITypeDeclaration} that is wrapping the design-time
+ * representation of the declaration description of a type.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+final class JpaTypeDeclaration implements ITypeDeclaration {
+
+	/**
+	 * The dimensionality of the array or 0 if the type is not an array.
+	 */
+	private int dimensionality;
+
+	/**
+	 * The generics of the given type or an empty list if the type is not parameterized.
+	 */
+	private final ITypeDeclaration[] genericTypes;
+
+	/**
+	 * The external form of the Java type.
+	 */
+	private final IType type;
+
+	/**
+	 * Creates a new <code>JpaTypeDeclaration</code>.
+	 *
+	 * @param type The external form of the Java type
+	 * @param genericTypes The generics of the given type or an empty list if the type is not
+	 * parameterized
+	 */
+	JpaTypeDeclaration(IType type, ITypeDeclaration[] genericTypes) {
+		this(type, genericTypes, 0);
+	}
+
+	/**
+	 * Creates a new <code>JpaTypeDeclaration</code>.
+	 *
+	 * @param type The external form of the Java type
+	 * @param genericTypes The generics of the given type or an empty list if the type is not
+	 * parameterized
+	 * @param dimensionality The dimensionality of the array or 0 if it's not an array
+	 */
+	JpaTypeDeclaration(IType type, ITypeDeclaration[] genericTypes, int dimensionality) {
+		super();
+		this.type           = type;
+		this.genericTypes   = genericTypes;
+		this.dimensionality = dimensionality;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public int getDimensionality() {
+		return dimensionality;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IType getType() {
+		return type;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public ITypeDeclaration[] getTypeParameters() {
+		return genericTypes;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isArray() {
+		return dimensionality > 0;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		return type.getName();
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaTypeRepository.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaTypeRepository.java
new file mode 100644
index 0000000..ece1dbd
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/JpaTypeRepository.java
@@ -0,0 +1,404 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.persistence.jpa.jpql.TypeHelper;
+import org.eclipse.persistence.jpa.jpql.spi.ITypeDeclaration;
+import org.eclipse.persistence.jpa.jpql.spi.ITypeRepository;
+
+/**
+ * The concrete implementation of {@link ITypeRepository} that is wrapping the design-time
+ * representation of a type repository.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+@SuppressWarnings("nls")
+final class JpaTypeRepository implements ITypeRepository {
+
+	/**
+	 * The Java project that gives access the design-time objects representing the Java types.
+	 */
+	private final IJavaProject javaProject;
+
+	/**
+	 * Keeps a map of the primitives for fast access.
+	 */
+	private Map<String, Class<?>> primitives;
+
+	/**
+	 * The cached helper that is using this repository for retrieving {@link IJpaType types}.
+	 */
+	private TypeHelper typeHelper;
+
+	/**
+	 * The types that have been cached for faster access.
+	 */
+	private final Map<String, IJpaType> types;
+
+	/**
+	 * The {@link IJpaType} that represents a unresolvable or simply an unknown type, which is created
+	 * when {@link #getType(String)} is invoked with {@link IJpaType#UNRESOLVABLE_TYPE}.
+	 */
+	private IJpaType unresolvableType;
+
+	/**
+	 * Creates a new <code>JpaTypeRepository</code>.
+	 *
+	 * @param javaProject The Java project that gives access the design-time objects representing
+	 * the Java types
+	 */
+	JpaTypeRepository(IJavaProject javaProject) {
+		super();
+		this.javaProject = javaProject;
+		this.types       = new HashMap<String, IJpaType>();
+	}
+
+	private String buildInnerTypeName(String typeName, int index) {
+		StringBuilder sb = new StringBuilder();
+		sb.append(typeName.substring(0, index));
+		sb.append("$");
+		sb.append(typeName.substring(index + 1, typeName.length()));
+		return sb.toString();
+	}
+
+	private Map<String, Class<?>> buildPrimitives() {
+		Map<String, Class<?>> primitives = new HashMap<String, Class<?>>();
+		primitives.put(Byte     .TYPE.getName(), Byte     .TYPE);
+		primitives.put(Short    .TYPE.getName(), Short    .TYPE);
+		primitives.put(Character.TYPE.getName(), Character.TYPE);
+		primitives.put(Integer  .TYPE.getName(), Integer  .TYPE);
+		primitives.put(Long     .TYPE.getName(), Long     .TYPE);
+		primitives.put(Float    .TYPE.getName(), Float    .TYPE);
+		primitives.put(Double   .TYPE.getName(), Double   .TYPE);
+		primitives.put(Boolean  .TYPE.getName(), Boolean  .TYPE);
+		return primitives;
+	}
+
+	private IJpaType buildType(Class<?> javaType) {
+		JavaType jpaType = new JavaType(this, javaType);
+		types.put(jpaType.getName(), jpaType);
+		return jpaType;
+	}
+
+	private IJpaType buildType(IType type) {
+		JpaType jpaType = new JpaType(this, type);
+		types.put(jpaType.getName(), jpaType);
+		return jpaType;
+	}
+
+	private IJpaType buildType(String typeName) {
+		IJpaType jpaType = new SimpleType(this, typeName);
+		types.put(typeName, jpaType);
+		return jpaType;
+	}
+
+	private String convertToJavaArrayType(String typeName) {
+
+		int index = typeName.indexOf("[]");
+		int dimensionality = (typeName.length() - index) / 2;
+		StringBuilder sb = new StringBuilder();
+
+		while (dimensionality-- > 0) {
+			sb.append("[");
+		}
+
+		String type = typeName.substring(0, index);
+		Class<?> primitive = primitives.get(type);
+
+		if (primitive != null) {
+			if (primitive == Byte.TYPE) {
+				sb.append("B");
+			}
+			else if (primitive == Character.TYPE) {
+				sb.append("C");
+			}
+			else if (primitive == Short.TYPE) {
+				sb.append("S");
+			}
+			else if (primitive == Integer.TYPE) {
+				sb.append("I");
+			}
+			else if (primitive == Long.TYPE) {
+				sb.append("L");
+			}
+			else if (primitive == Float.TYPE) {
+				sb.append("F");
+			}
+			else if (primitive == Double.TYPE) {
+				sb.append("D");
+			}
+			else if (primitive == Boolean.TYPE) {
+				sb.append("Z");
+			}
+		}
+		else {
+			sb.append(type);
+			sb.append(";");
+		}
+
+		return sb.toString();
+	}
+
+	private Class<?> findPrimitive(String typeName) {
+		if (primitives == null) {
+			primitives = buildPrimitives();
+		}
+		return primitives.get(typeName);
+	}
+
+	/**
+	 * Retrieves the design-time Java type for the given type name, which has to be the fully
+	 * qualified type name.
+	 *
+	 * @param typeName The fully qualified type name
+	 * @return The design-time Java type if it could be retrieved; <code>null</code> otherwise
+	 */
+	IType findType(String typeName) {
+		try {
+			return javaProject.findType(typeName);
+		}
+		catch (JavaModelException e) {
+			return null;
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IJpaType getEnumType(String enumTypeName) {
+
+		// Get the position of the last dot so the enum constant can be removed
+		int lastDotIndex = enumTypeName.lastIndexOf(".");
+
+		if (lastDotIndex == -1) {
+			return null;
+		}
+
+		// Retrieve the fully qualified enum type name
+		String typeName = enumTypeName.substring(0, lastDotIndex);
+
+		// Attempt to load the enum type
+		IType type = findType(typeName);
+		IJpaType jpaType;
+
+		if (type != null) {
+			jpaType = buildType(type);
+		}
+		else {
+			jpaType = loadInnerType(typeName);
+		}
+
+		return (jpaType != null) && jpaType.isEnum() ? jpaType : null;
+	}
+
+	/**
+	 * Returns the Java project, which gives access to the class path.
+	 *
+	 * @return The Java project, which gives access to the class path
+	 */
+	IJavaProject getJavaProject() {
+		return javaProject;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IJpaType getType(Class<?> javaClass) {
+		IJpaType type = types.get(javaClass.getName());
+		if (type == null) {
+			type = buildType(javaClass);
+		}
+		return type;
+	}
+
+	/**
+	 * Retrieves the {@link IType} for the given {@link IResource}.
+	 *
+	 * @param resource The workspace location of the {@link IType} to retrieve
+	 * @return The design-time representation of a Java type
+	 */
+	IType getType(IResource resource) {
+		try {
+			return (IType) javaProject.findElement((IPath) resource);
+		}
+		catch (Exception e) {
+			return null;
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IJpaType getType(String typeName) {
+
+		if (IJpaType.UNRESOLVABLE_TYPE == typeName) {
+			return unresolvableType();
+		}
+
+		if (typeName.endsWith("[]")) {
+			return loadArrayType(typeName);
+		}
+
+		if (typeName.charAt(0) == '[') {
+			return loadJavaArrayType(typeName);
+		}
+
+		return loadTypeImp(typeName);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public TypeHelper getTypeHelper() {
+		if (typeHelper == null) {
+			typeHelper = new TypeHelper(this);
+		}
+		return typeHelper;
+	}
+
+	private IJpaType loadArrayType(String typeName) {
+
+		IJpaType type = types.get(typeName);
+
+		if (type == null) {
+			try {
+				// Try to see if the type is a JDK class, otherwise, just use the type name
+				// since IJpaType doesn't support array types
+				String javaTypeName = convertToJavaArrayType(typeName);
+				type = buildType(Class.forName(javaTypeName));
+			}
+			catch (Exception e) {
+
+				int index = typeName.indexOf("[]");
+				int dimensionality = (typeName.length() - index) / 2;
+
+				type = getType(typeName.substring(0, index));
+
+				type.setTypeDeclaration(
+					new JpaTypeDeclaration(type, new ITypeDeclaration[0], dimensionality)
+				);
+			}
+
+			types.put(typeName, type);
+		}
+
+		return type;
+	}
+
+	private IJpaType loadInnerType(String typeName) {
+
+		while (true) {
+
+			int index = typeName.lastIndexOf(".");
+
+			if (index == -1) {
+				return null;
+			}
+
+			typeName = buildInnerTypeName(typeName, index);
+			IJpaType cachedType = types.get(typeName);
+
+			if (cachedType != null) {
+				return cachedType;
+			}
+
+			// Attempt to load the Java type
+			IType type = findType(typeName);
+
+			// A Java type exists, return it
+			if (type != null) {
+				return buildType(type);
+			}
+		}
+	}
+
+	private IJpaType loadJavaArrayType(String typeName) {
+
+		IJpaType type = types.get(typeName);
+
+		if (type == null) {
+			try {
+				// Try to see if the type is a JDK class, otherwise, just use the type name
+				// since IJpaType doesn't support array types
+				type = buildType(Class.forName(typeName));
+			}
+			catch (Exception e) {
+
+				int index = typeName.lastIndexOf("[");
+				int dimensionality = index / 2;
+
+				type = getType(typeName.substring(index, typeName.endsWith(";") ? typeName.length() - 1 : typeName.length()));
+
+				type.setTypeDeclaration(
+					new JpaTypeDeclaration(type, new ITypeDeclaration[0], dimensionality)
+				);
+			}
+
+			types.put(typeName, type);
+		}
+
+		return type;
+	}
+
+	private IJpaType loadTypeImp(String typeName) {
+
+		IJpaType type = types.get(typeName);
+
+		// The type was already cached, simply return it
+		if (type != null) {
+			return type;
+		}
+
+		// First check for primitive, they don't have a corresponding IJpaType
+		Class<?> primitive = findPrimitive(typeName);
+
+		if (primitive != null) {
+			return buildType(primitive);
+		}
+
+		// Attempt to load the Java type
+		IType iType = findType(typeName);
+
+		// A Java type exists, return it
+		if (iType != null) {
+			return buildType(iType);
+		}
+
+		// Now try with a possible inner enum type
+		type = loadInnerType(typeName);
+
+		// No Java type exists, create a "null" IJpaType
+		if (type == null) {
+			type = buildType(typeName);
+		}
+
+		return type;
+	}
+
+	private IJpaType unresolvableType() {
+		if (unresolvableType == null) {
+			unresolvableType = new SimpleType(this, IJpaType.UNRESOLVABLE_TYPE);
+		}
+		return unresolvableType;
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/SimpleType.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/SimpleType.java
new file mode 100644
index 0000000..b302482
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/jpql/SimpleType.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.core.internal.jpql;
+
+import java.lang.annotation.Annotation;
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.jpt.common.utility.internal.iterables.EmptyIterable;
+import org.eclipse.persistence.jpa.jpql.spi.IConstructor;
+import org.eclipse.persistence.jpa.jpql.spi.IType;
+import org.eclipse.persistence.jpa.jpql.spi.ITypeDeclaration;
+
+/**
+ * The concrete implementation of {@link IType} that is wrapping the type name only.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+final class SimpleType implements IJpaType {
+
+	/**
+	 * Caches the type hierarchy of the {@link IType} in order to prevent rebuilding it each time.
+	 */
+	private ITypeDeclaration typeDeclaration;
+
+	/**
+	 * The fully qualified name of the Java type.
+	 */
+	private final String typeName;
+
+	/**
+	 * The external form of a type repository.
+	 */
+	private final JpaTypeRepository typeRepository;
+
+	/**
+	 * Creates a new <code>SimpleType</code>.
+	 *
+	 * @param typeName The fully qualified name of the Java type
+	 */
+	SimpleType(JpaTypeRepository typeRepository, String typeName) {
+		super();
+		this.typeRepository = typeRepository;
+		this.typeName       = typeName;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Iterable<IConstructor> constructors() {
+		return EmptyIterable.instance();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean equals(IType type) {
+		return typeName.equals(type.getName());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String[] getEnumConstants() {
+		return StringTools.EMPTY_STRING_ARRAY;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String getName() {
+		return typeName;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public ITypeDeclaration getTypeDeclaration() {
+		if (typeDeclaration == null) {
+			typeDeclaration = new JpaTypeDeclaration(this, new ITypeDeclaration[0]);
+		}
+		return typeDeclaration;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean hasAnnotation(Class<? extends Annotation> annotationType) {
+		return false;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isAssignableTo(IType type) {
+		return typeRepository.equals(type.getName());
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isEnum() {
+		return false;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public boolean isResolvable() {
+		return false;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void setTypeDeclaration(JpaTypeDeclaration typeDeclaration) {
+		this.typeDeclaration = typeDeclaration;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String toString() {
+		return typeName;
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/validation/JpaValidationMessages.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/validation/JpaValidationMessages.java
index 36b556e..c7baee0 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/validation/JpaValidationMessages.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/internal/validation/JpaValidationMessages.java
@@ -3,7 +3,7 @@
  * 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
  ******************************************************************************/
@@ -13,7 +13,7 @@
 public interface JpaValidationMessages {
 
 	public static final String BUNDLE_NAME = "jpa_validation";
-	
+
 	public static final String PROJECT_INVALID_LIBRARY_PROVIDER = "PROJECT_INVALID_LIBRARY_PROVIDER";
 	public static final String PROJECT_NO_CONNECTION = "PROJECT_NO_CONNECTION";
 	public static final String PROJECT_INVALID_CONNECTION = "PROJECT_INVALID_CONNECTION";
@@ -43,6 +43,7 @@
 	public static final String GENERATOR_NAME_UNDEFINED = "GENERATOR_NAME_UNDEFINED";
 	public static final String QUERY_DUPLICATE_NAME = "QUERY_DUPLICATE_NAME";
 	public static final String QUERY_NAME_UNDEFINED = "QUERY_NAME_UNDEFINED";
+	public static final String JPQL_QUERY_VALIDATION = "JPQL_QUERY_VALIDATION";
 	public static final String QUERY_STATEMENT_UNDEFINED = "QUERY_STATEMENT_UNDEFINED";
 	public static final String MAPPING_FILE_EXTRANEOUS_PERSISTENCE_UNIT_METADATA = "MAPPING_FILE_EXTRANEOUS_PERSISTENCE_UNIT_METADATA";
 	public static final String PERSISTENT_TYPE_MAPPED_BUT_NOT_INCLUDED_IN_PERSISTENCE_UNIT = "PERSISTENT_TYPE_MAPPED_BUT_NOT_INCLUDED_IN_PERSISTENCE_UNIT";
@@ -158,7 +159,7 @@
 	public static final String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_NAME = "VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_NAME";
 	public static final String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_CATALOG = "VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_CATALOG";
 	public static final String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_SCHEMA = "VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_SCHEMA";
-	
+
 	public static final String GENERATED_VALUE_UNRESOLVED_GENERATOR = "GENERATED_VALUE_UNRESOLVED_GENERATOR";
 	public static final String PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_NAME = "PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_NAME";
 	public static final String PRIMARY_KEY_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS = "PRIMARY_KEY_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS";
@@ -176,7 +177,7 @@
 	public static final String VIRTUAL_SECONDARY_TABLE_PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME = "VIRTUAL_SECONDARY_TABLE_PRIMARY_KEY_JOIN_COLUMN_UNRESOLVED_REFERENCED_COLUMN_NAME";
 	public static final String VIRTUAL_SECONDARY_TABLE_PRIMARY_KEY_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS = "VIRTUAL_SECONDARY_TABLE_PRIMARY_KEY_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS";
 	public static final String VIRTUAL_SECONDARY_TABLE_PRIMARY_KEY_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS = "VIRTUAL_SECONDARY_TABLE_PRIMARY_KEY_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS";
-	
+
 	public static final String NO_JPA_PROJECT = "NO_JPA_PROJECT";
 	public static final String TARGET_ENTITY_NOT_DEFINED = "TARGET_ENTITY_NOT_DEFINED";
 	public static final String VIRTUAL_ATTRIBUTE_TARGET_ENTITY_NOT_DEFINED = "VIRTUAL_ATTRIBUTE_TARGET_ENTITY_NOT_DEFINED";
@@ -186,7 +187,7 @@
 	public static final String ENTITY_TABLE_PER_CLASS_NOT_SUPPORTED_ON_PLATFORM = "ENTITY_TABLE_PER_CLASS_NOT_SUPPORTED_ON_PLATFORM";
 	public static final String ENTITY_TABLE_PER_CLASS_NOT_PORTABLE_ON_PLATFORM = "ENTITY_TABLE_PER_CLASS_NOT_PORTABLE_ON_PLATFORM";
 	public static final String TARGET_NOT_AN_EMBEDDABLE = "TARGET_NOT_AN_EMBEDDABLE";
-	
+
 	public static final String COLUMN_TABLE_NOT_VALID="COLUMN_TABLE_NOT_VALID";
 	public static final String VIRTUAL_ATTRIBUTE_COLUMN_TABLE_NOT_VALID="VIRTUAL_ATTRIBUTE_COLUMN_TABLE_NOT_VALID";
 	public static final String VIRTUAL_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID="VIRTUAL_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID";
@@ -228,5 +229,4 @@
 	public static final String VIRTUAL_ATTRIBUTE_MAP_KEY_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID="VIRTUAL_ATTRIBUTE_MAP_KEY_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID";
 	public static final String MAP_KEY_COLUMN_TABLE_NOT_VALID="MAP_KEY_COLUMN_TABLE_NOT_VALID";
 	public static final String VIRTUAL_ATTRIBUTE_MAP_KEY_COLUMN_TABLE_NOT_VALID="VIRTUAL_ATTRIBUTE_MAP_KEY_COLUMN_TABLE_NOT_VALID";
-
-}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/resource/orm/XmlNamedNativeQuery.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/resource/orm/XmlNamedNativeQuery.java
index 024f72f..fae596a 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/resource/orm/XmlNamedNativeQuery.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/resource/orm/XmlNamedNativeQuery.java
@@ -3,7 +3,7 @@
  * 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
  ******************************************************************************/
@@ -29,7 +29,7 @@
 /**
  * <!-- begin-user-doc -->
  * A representation of the model object '<em><b>Named Native Query</b></em>'.
- * 
+ *
  * Provisional API: This interface is part of an interim API that is still
  * under development and expected to change significantly before reaching
  * stability. It is available at this early stage to solicit feedback from
@@ -538,11 +538,15 @@
 		result.append(')');
 		return result.toString();
 	}
-	
+
 	public TextRange getNameTextRange() {
 		return getAttributeTextRange(JPA.NAME);
 	}
-	
+
+	public TextRange getQueryTextRange() {
+		return getAttributeTextRange(JPA.QUERY);
+	}
+
 	// ********** translators **********
 
 	public static Translator buildTranslator(String elementName, EStructuralFeature structuralFeature) {
@@ -563,23 +567,23 @@
 	protected static Translator buildNameTranslator() {
 		return new Translator(JPA.NAME, OrmPackage.eINSTANCE.getXmlQuery_Name(), Translator.DOM_ATTRIBUTE);
 	}
-	
+
 	protected static Translator buildResultClassTranslator() {
 		return new Translator(JPA.RESULT_CLASS, OrmPackage.eINSTANCE.getXmlNamedNativeQuery_ResultClass(), Translator.DOM_ATTRIBUTE);
 	}
-	
+
 	protected static Translator buildResultSetMappingTranslator() {
 		return new Translator(JPA.RESULT_SET_MAPPING, OrmPackage.eINSTANCE.getXmlNamedNativeQuery_ResultSetMapping(), Translator.DOM_ATTRIBUTE);
 	}
-	
+
 	protected static Translator buildDescriptionTranslator() {
 		return new Translator(JPA2_0.DESCRIPTION, OrmV2_0Package.eINSTANCE.getXmlQuery_2_0_Description());
 	}
-	
+
 	protected static Translator buildQueryTranslator() {
 		return new Translator(JPA.QUERY, OrmPackage.eINSTANCE.getXmlQuery_Query());
 	}
-	
+
 	protected static Translator buildHintTranslator() {
 		return XmlQueryHint.buildTranslator(JPA.HINT, OrmPackage.eINSTANCE.getXmlQuery_Hints());
 	}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/resource/orm/XmlNamedQuery.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/resource/orm/XmlNamedQuery.java
index 0c4cc5e..61d0a7b 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/resource/orm/XmlNamedQuery.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/resource/orm/XmlNamedQuery.java
@@ -3,7 +3,7 @@
  * 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
  ******************************************************************************/
@@ -19,6 +19,7 @@
 import org.eclipse.emf.ecore.impl.ENotificationImpl;
 import org.eclipse.emf.ecore.util.EObjectContainmentEList;
 import org.eclipse.emf.ecore.util.InternalEList;
+import org.eclipse.jpt.common.core.internal.utility.SimpleTextRange;
 import org.eclipse.jpt.common.core.internal.utility.translators.SimpleTranslator;
 import org.eclipse.jpt.common.core.utility.TextRange;
 import org.eclipse.jpt.jpa.core.resource.orm.v2_0.JPA2_0;
@@ -27,11 +28,12 @@
 import org.eclipse.jpt.jpa.core.resource.orm.v2_0.XmlNamedQuery_2_0;
 import org.eclipse.jpt.jpa.core.resource.xml.AbstractJpaEObject;
 import org.eclipse.wst.common.internal.emf.resource.Translator;
+import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
 
 /**
  * <!-- begin-user-doc -->
  * A representation of the model object '<em><b>Named Query</b></em>'.
- * 
+ *
  * Provisional API: This interface is part of an interim API that is still
  * under development and expected to change significantly before reaching
  * stability. It is available at this early stage to solicit feedback from
@@ -503,11 +505,31 @@
 		result.append(')');
 		return result.toString();
 	}
-	
+
 	public TextRange getNameTextRange() {
 		return getAttributeTextRange(JPA.NAME);
 	}
-	
+
+	public TextRange getQueryTextRange() {
+		// <named-query>
+		IDOMNode node = getElementNode(JPA.QUERY);
+		if (node != null) {
+			// The query element has text
+			if (node.hasChildNodes()) {
+				return buildTextRange((IDOMNode) node.getFirstChild());
+			}
+			// The query element does not have text
+			TextRange textRange = buildTextRange(node);
+			return new SimpleTextRange(
+				node.getEndStructuredDocumentRegion().getStartOffset(),
+				0,
+				textRange.getLineNumber()
+			);
+		}
+
+		return this.getValidationTextRange();
+	}
+
 	// ********** translators **********
 
 	public static Translator buildTranslator(String elementName, EStructuralFeature structuralFeature) {
@@ -527,15 +549,15 @@
 	protected static Translator buildNameTranslator() {
 		return new Translator(JPA.NAME, OrmPackage.eINSTANCE.getXmlQuery_Name(), Translator.DOM_ATTRIBUTE);
 	}
-	
+
 	protected static Translator buildDescriptionTranslator() {
 		return new Translator(JPA2_0.DESCRIPTION, OrmV2_0Package.eINSTANCE.getXmlQuery_2_0_Description());
 	}
-	
+
 	protected static Translator buildQueryTranslator() {
 		return new Translator(JPA.QUERY, OrmPackage.eINSTANCE.getXmlQuery_Query());
 	}
-	
+
 	protected static Translator buildLockModeTranslator() {
 		return new Translator(JPA2_0.NAMED_QUERY__LOCK_MODE, OrmV2_0Package.eINSTANCE.getXmlNamedQuery_2_0_LockMode());
 	}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/resource/orm/XmlQuery.java b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/resource/orm/XmlQuery.java
index 9161893..df6fded 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/resource/orm/XmlQuery.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.core/src/org/eclipse/jpt/jpa/core/resource/orm/XmlQuery.java
@@ -3,7 +3,7 @@
  * 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
  ******************************************************************************/
@@ -16,7 +16,7 @@
 /**
  * <!-- begin-user-doc -->
  * A representation of the model object '<em><b>Query</b></em>'.
- * 
+ *
  * Provisional API: This interface is part of an interim API that is still
  * under development and expected to change significantly before reaching
  * stability. It is available at this early stage to solicit feedback from
@@ -106,6 +106,8 @@
 	 * @generated
 	 */
 	EList<XmlQueryHint> getHints();
-	
-	public TextRange getNameTextRange();
+
+	TextRange getNameTextRange();
+
+	TextRange getQueryTextRange();
 }
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/META-INF/MANIFEST.MF b/jpa/plugins/org.eclipse.jpt.jpa.ui/META-INF/MANIFEST.MF
index f21a841..14f4365 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/META-INF/MANIFEST.MF
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/META-INF/MANIFEST.MF
@@ -32,6 +32,7 @@
  org.eclipse.jst.common.project.facet.ui;bundle-version="[1.3.100,2.0.0)",
  org.eclipse.jst.j2ee;bundle-version="[1.1.200,2.0.0)",
  org.eclipse.jst.j2ee.ui;bundle-version="[1.1.200,2.0.0)",
+ org.eclipse.persistence.jpa.jpql;bundle-version="[1.0.0,2.0.0)",
  org.eclipse.ui.ide;bundle-version="[3.4.0,4.0.0)",
  org.eclipse.ui.views.properties.tabbed;bundle-version="[3.4.0,4.0.0)",
  org.eclipse.ui.navigator;bundle-version="[3.3.100,4.0.0)",
@@ -41,6 +42,7 @@
  org.eclipse.wst.common.frameworks.ui;bundle-version="[1.1.200,2.0.0)",
  org.eclipse.wst.common.project.facet.ui;bundle-version="[1.3.0,2.0.0)",
  org.eclipse.wst.sse.ui;bundle-version="[1.1.0,2.0.0)",
+ org.eclipse.wst.validation;bundle-version="[1.2.0,2.0.0)",
  org.eclipse.wst.web.ui;bundle-version="[1.1.200,2.0.0)"
 Export-Package: org.eclipse.jpt.jpa.ui,
  org.eclipse.jpt.jpa.ui.details,
@@ -64,6 +66,7 @@
  org.eclipse.jpt.jpa.ui.internal.jpa2.persistence.connection;x-internal:=true,
  org.eclipse.jpt.jpa.ui.internal.jpa2.persistence.options;x-internal:=true,
  org.eclipse.jpt.jpa.ui.internal.jpa2.platform.generic;x-internal:=true,
+ org.eclipse.jpt.jpa.ui.internal.jpql;x-internal:=true,
  org.eclipse.jpt.jpa.ui.internal.listeners;x-internal:=true,
  org.eclipse.jpt.jpa.ui.internal.menus;x-internal:=true,
  org.eclipse.jpt.jpa.ui.internal.navigator;x-internal:=true,
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/icons/full/obj16/jpql.function.gif b/jpa/plugins/org.eclipse.jpt.jpa.ui/icons/full/obj16/jpql.function.gif
new file mode 100644
index 0000000..c94434c
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/icons/full/obj16/jpql.function.gif
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/icons/full/obj16/jpql.identifier.gif b/jpa/plugins/org.eclipse.jpt.jpa.ui/icons/full/obj16/jpql.identifier.gif
new file mode 100644
index 0000000..b6d82ff
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/icons/full/obj16/jpql.identifier.gif
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/icons/full/obj16/jpql.variable.gif b/jpa/plugins/org.eclipse.jpt.jpa.ui/icons/full/obj16/jpql.variable.gif
new file mode 100644
index 0000000..a5c6124
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/icons/full/obj16/jpql.variable.gif
Binary files differ
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/plugin.xml b/jpa/plugins/org.eclipse.jpt.jpa.ui/plugin.xml
index 0aaec82..d144e36 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/plugin.xml
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/plugin.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?eclipse version="3.2"?>
 <!--
-  Copyright (c) 2007, 2010 Oracle. All rights reserved.
+  Copyright (c) 2007, 2011 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.
@@ -69,10 +69,9 @@
 			<partition type="__dftl_partition_content_type"/>
 			<partition type="__java_string"/>
 		</javaCompletionProposalComputer>
-		
+
 	</extension>
-	
-	
+
 	<extension
 		point="org.eclipse.jdt.ui.javaCompletionProposalComputer"
 		id="jpaProposalCategory"
@@ -80,8 +79,45 @@
 		<proposalCategory
 			icon="$nl$/icons/full/eview16/jpa_perspective.gif"/>
 	</extension>
-	
-	
+
+	<extension
+		point="org.eclipse.jdt.ui.javaCompletionProposalComputer"
+		id="JpaJpqlCompletionProposalComputer">
+
+		<javaCompletionProposalComputer
+        activate="true"
+        categoryId="org.eclipse.jpt.jpa.ui.jpaProposalCategory"
+        class="org.eclipse.jpt.jpa.ui.internal.jpql.JpaJpqlJavaCompletionProposalComputer">
+			<partition type="__dftl_partition_content_type"/>
+			<partition type="__java_string"/>
+		</javaCompletionProposalComputer>
+		
+	</extension>
+
+	 <extension
+	       id="JpaJpqlSseCompletionProposal"
+	       point="org.eclipse.wst.sse.ui.completionProposal">
+	    <proposalComputer
+	          activate="true"
+	          categoryId="org.eclipse.wst.xml.ui.proposalCategory.xmlTags"
+	          class="org.eclipse.jpt.jpa.ui.internal.jpql.JpaJpqlSseCompletionProposalComputer"
+	          id="org.eclipse.jpt.jpa.ui.internal.jpql.JpaJpqlSseCompletionProposalComputer">
+	       <contentType
+	             id="org.eclipse.jpt.jpa.core.content.mappingFile">
+	       </contentType>
+	    </proposalComputer>
+	    <proposalComputer
+	          activate="true"
+	          categoryId="org.eclipse.wst.xml.ui.proposalCategory.xmlTags"
+	          class="org.eclipse.jpt.jpa.ui.internal.jpql.JpaJpqlSseCompletionProposalComputer"
+	          id="org.eclipse.jpt.jpa.ui.internal.jpql.JpaJpqlSseCompletionProposalComputer">
+	       <contentType
+	             id="org.eclipse.jpt.jpa.eclipselink.core.content.orm">
+	       </contentType>
+	    </proposalComputer>
+	 </extension>	
+
+
 	<extension
 		point="org.eclipse.jpt.jpa.ui.jpaPlatformUis">
 		
@@ -94,7 +130,7 @@
 			id="generic2_0.ui"
 			jpaPlatform="generic2_0"
 			factoryClass="org.eclipse.jpt.jpa.ui.internal.jpa2.platform.generic.Generic2_0JpaPlatformUiFactory"/>
-		
+	
 	</extension>
   	
 	
@@ -1035,5 +1071,12 @@
 		</wizard-pages>
 		
 	</extension>
+ <extension
+       id="org.eclipse.jpt.jpa.ui"
+       point="org.eclipse.core.runtime.preferences">
+    <initializer
+          class="org.eclipse.jpt.jpa.ui.internal.prefs.JpaUiPreferenceInitializer">
+    </initializer>
+ </extension>
  	
 </plugin>
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/property_files/jpt_ui.properties b/jpa/plugins/org.eclipse.jpt.jpa.ui/property_files/jpt_ui.properties
index 53b8bf0..264462b 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/property_files/jpt_ui.properties
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/property_files/jpt_ui.properties
@@ -118,7 +118,12 @@
 JpaMakePersistentWizardPage_mappingFileDoesNotExistError=The XML mapping file does not exist
 JpaMakePersistentWizardPage_mappingFileNotListedInPersistenceXmlError=The XML mapping file is not listed in the persistence.xml
 
-JpaPreferencesPage_Description=Expand the tree to edit preferences for a particular JPA feature.
+JpaPreferencesPage_description=General settings for JPA development:
+JpaPreferencesPage_jpqlEditor=JPQL Editing
+JpaPreferencesPage_jpqlEditor_description=Specify the case for JPQL identifiers used with content assist.
+JpaPreferencesPage_jpqlEditor_lowerCaseRadioButton=&Lowercase
+JpaPreferencesPage_jpqlEditor_matchFirstCharacterCaseRadioButton=&Match Case of First Character
+JpaPreferencesPage_jpqlEditor_upperCaseRadioButton=&Uppercase
 
 JpaProblemSeveritiesPage_Description=Select the severity level for the following optional Java Persistence validation problems:
 JpaProblemSeveritiesPage_Error=Error
@@ -126,6 +131,10 @@
 JpaProblemSeveritiesPage_Info=Info
 JpaProblemSeveritiesPage_Warning=Warning
 
+JpqlContentProposalProvider_Description=Content Assist Available ({0})
+JpaJpqlJavaCompletionProposalComputer_Error=Can't retrieve JPQL proposals due to an internal error.
+JpaJpqlSseCompletionProposalComputer_Error=Can't retrieve JPQL proposals due to an internal error.
+
 MappingFileWizard_title=New Mapping File
 MappingFileWizardPage_newFile_title=Mapping file
 MappingFileWizardPage_newFile_desc=Specify mapping file name and location
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/property_files/jpt_ui_jpql_identifiers.properties b/jpa/plugins/org.eclipse.jpt.jpa.ui/property_files/jpt_ui_jpql_identifiers.properties
new file mode 100644
index 0000000..f686262
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/property_files/jpt_ui_jpql_identifiers.properties
@@ -0,0 +1,83 @@
+################################################################################
+# Copyright (c) 2011 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.
+# 
+# Contributors:
+#     Oracle - initial API and implementation
+################################################################################
+
+# JPA 1.0 identifiers
+ABS=The <b>ABS</b> function removes the minus sign from a specified numeric argument and returns the absolute value (integer, float, or double) of the same type as the argument to the function, which is always a positive number or zero.
+ALL=<ul><li>An <b>ALL</b> conditional expression is a predicate that is <code>true</code> if the comparison operation is <code>true</code> for all values in the result of the subquery or the result of the subquery is empty.</li><li>An <b>ALL</b> conditional expression is <code>false</code> if the result of the comparison is <code>false</code> for at least one row, and is unknown if neither <code>true</code> nor <code>false</code>.</ul><p><p>The comparison operators used with <b>ALL</b> conditional expressions are =, <, <=, >, >=, <>.<p><p>The result of the subquery must be like that of the other argument to the comparison operator in type.
+#AND
+ANY=<ul><li>An <b>ANY</b> conditional expression is a predicate that is <code>true</code> if the comparison operation is <code>true</code> for some value in the result of the subquery.</li><li>An <b>ANY</b> conditional expression is <code>false</code> if the result of the subquery is empty or if the comparison operation is <code>false</code> for every value in the result of the subquery,</li><li>and is unknown if neither <code>true</code> nor <code>false</code>.</li></ul><p><p>The comparison operators used with <b>ANY</b> conditional expressions are =, <, <=, >, >=, <>.<p><p>The result of the subquery must be like that of the other argument to the comparison operator in type.
+ASC=The keyword <b>ASC</b> specifies that ascending ordering be used for the associated order by item.
+AVG=One of the aggregate functions. The arguments must be numeric. <b>AVG</b> returns <code>Double</code>.<p><p><b>BNF:</b> <code>expression ::= AVG([DISTINCT] state_field_path_expression)</code>
+BETWEEN=Used in conditional expression to determine whether the result of an expression falls within an inclusive range of values. Numeric, string and date expression can be evaluated in this way.
+BOTH=Trim from both ends.
+CONCAT=The <b>CONCAT</b> function returns a string that is a concatenation of its arguments.
+COUNT=One of the aggregate functions. The return type of this function is a <code>Long</code>.
+CURRENT_DATE=This function returns the value of current date on the database server.
+CURRENT_TIME=This function returns the value of current time on the database server.
+CURRENT_TIMESTAMP=This function returns the value of current timestamp on the database
+DELETE_FROM=A delete statement provide bulk operations over sets of entities.
+DESC=The keyword <b>DESC</b> specifies that descending ordering be used. Ascending ordering is the default.
+DISTINCT=The <b>DISTINCT</b> keyword is used to specify that duplicate values must be eliminated from the query result. If <b>DISTINCT</b> is not specified, duplicate values are not eliminated.
+ESCAPE=The optional <code>escape character</code> is a single-character string literal or a character-valued input parameter (i.e., char or Character) and is used to escape the special meaning of the underscore and percent characters in <code>pattern value</code>.
+EXISTS=An <b>EXISTS</b> expression is a predicate that is <code>true</code> only if the result of the subquery consists of one or more values and that is <code>false</code> otherwise.
+FROM=The <b>FROM</b> clause of a query defines the domain of the query by declaring identification variables. An identification variable is an identifier declared in the <b>FROM</b> clause of a query. The domain of the query may be constrained by path expressions. Identification variables designate instances of a particular entity abstract schema type. The <b>FROM</b> clause can contain multiple identification variable declarations separated by a comma (,).
+GROUP_BY=The <b>GROUP BY</b> construct enables the aggregation of values according to the properties of an entity class.
+HAVING=The <b>HAVING</b> construct enables conditions to be specified that further restrict the query result as restrictions upon the groups.
+IN=An identification variable declared by a collection member declaration ranges over values of a collection obtained by navigation using a path expression. Such a path expression represents a navigation involving the association-fields of an entity abstract schema type. Because a path expression can be based on another path expression, the navigation can use the association-fields of related entities. An identification variable of a collection member declaration is declared using a special operator, the reserved identifier <b>IN</b>. The argument to the <b>IN</b> operator is a collection-valued path expression. The path expression evaluates to a collection type specified as a result of navigation to a collection-valued association-field of an entity abstract schema type.
+IS_EMPTY=An <b>EMPTY</b> expression tests whether or not the collection designated by the collection-valued path expression is empty (i.e, has no elements).
+IS_NULL=A null comparison tests whether or not the single-valued path expression or input parameter is a <b>NULL</b> value.
+JOIN=A <b>JOIN</b> enables the fetching of an association as a side effect of the execution of a query. A <b>JOIN</b> is specified over an entity and its related entities.
+JOIN_FETCH=A <b>JOIN FETCH</b> enables the fetching of an association as a side effect of the execution of a query. A <b>JOIN FETCH</b> is specified over an entity and its related entities.
+LEADING=Trim from leading end.
+LENGTH=The <b>LENGTH</b> function returns the length of the string in characters as an integer.
+LIKE=The <b>LIKE</b> condition is used to specify a search for a pattern.<p><p>The <code>string_expression</code> must have a string value. The <code>pattern_value</code> is a string literal or a string-valued input parameter in which an underscore (_) stands for any single character, a percent (%) character stands for any sequence of characters (including the empty sequence), and all other characters stand for themselves. The optional <code>escape_character</code> is a single-character string literal or a character-valued input parameter (i.e., char or Character) and is used to escape the special meaning of the underscore and percent characters in <code>pattern_value</code>.
+LOCATE=The <b>LOCATE</b> function returns the position of a given string within a string, starting the search at a specified position. It returns the first position at which the string was found as an integer. The first argument is the string to be located; the second argument is the string to be searched; the optional third argument is an integer that represents the string position at which the search is started (by default, the beginning of the string to be searched). The first position in a string is denoted by 1. If the string is not found, 0 is returned. The <b>LENGTH</b> function returns the length of the string in characters as an integer.
+LOWER=The <b>LOWER</b> function converts a string to lower case and it returns a string.
+MAX=One of the aggregate functions. The arguments must correspond to orderable state-field types (i.e., numeric types, string types, character types, or date types). The return type of this function is based on the state-field's type.
+MEMBER=This expression tests whether the designated value is a member of the collection specified by the collection-valued path expression. If the collection-valued path expression designates an empty collection, the value of the <b>MEMBER OF</b> expression is <b>FALSE</b> and the value of the <b>NOT MEMBER OF</b> expression is <b>TRUE</b>. Otherwise, if the value of the collection-valued path expression or single-valued association-field path expression in the collection member expression is <b>NULL</b> or unknown, the value of the collection member expression is unknown.
+MIN= One of the aggregate functions. The arguments must correspond to orderable state-field types (i.e., numeric types, string types, character types, or date types). The return type of this function is based on the state-field's type.
+MOD=The modulo operation finds the remainder of division of one number by another. It takes two integer arguments and returns an integer.
+NEW=In the <b>SELECT</b> clause a constructor may be used in the <b>SELECT</b> list to return one or more Java instances. The specified class is not required to be an entity or to be mapped to the database. The constructor name must be fully qualified.
+OBJECT=Stand-alone identification variables in the <b>SELECT</b> clause may optionally be qualified by the <b>OBJECT</b> operator. The <b>SELECT</b> clause must not use the <b>OBJECT</b> operator to qualify path expressions.
+#OR
+ORDER_BY=The <b>ORDER BY</b> clause allows the objects or values that are returned by the query to be ordered.
+SELECT=The <b>SELECT</b> clause determines the type of the objects or values to be selected.
+SIZE=The <b>SIZE</b> function returns an integer value, the number of elements of the collection. If the collection is empty, the <b>SIZE</b> function evaluates to zero.
+SOME=<ul><li>An <b>SOME</b> conditional expression is a predicate that is <code>true</code> if the comparison operation is <code>true</code> for some value in the result of the subquery.</li><li>A <b>SOME</b> conditional expression is <code>false</code> if the result of the subquery is empty or if the comparison operation is <code>false</code> for every value in the result of the subquery,</li><li>and is unknown if neither <code>true</code> nor <code>false</code>.</li></ul><p><p>The comparison operators used with <b>SOME</b> conditional expressions are =, <, <=, >, >=, <>.<p><p>The result of the subquery must be like that of the other argument to the comparison operator in type.
+SQRT=The <b>SQRT</b> function takes a numeric argument and returns a double.
+SUBSTRING=The second and third arguments of the <b>SUBSTRING</b> function denote the starting position and length of the substring to be returned. These arguments are integers. The first position of a string is denoted by 1. The <b>SUBSTRING</b> function returns a string.
+SUM= One of the aggregate functions. The arguments must be numeric. The <b>SUM</b> function returns <code>Long</code> when applied to state-fields of integral types (other than <code>BigInteger</code>); <code>Double</code> when applied to state-fields of floating point types; <code>BigInteger</code> when applied to state-fields of type <code>BigInteger</code>; and <code>BigDecimal</code> when applied to state-fields of type <code>BigDecimal</code>. If <b>SUM</b>, <b>AVG</b>, <b>MAX</b>, or <b>MIN</b> is used, and there are no values to which the aggregate function can be applied, the result of the aggregate function is <code>NULL</code>. If <code>COUNT</code> is used, and there are no values to which <b>COUNT</b> can be applied, the result of the aggregate function is 0.
+TRAILING=Trim from trailing end.
+TRIM=The <b>TRIM</b> function trims the specified character from a string. If the character to be trimmed is not specified, it is assumed to be space (or blank). The optional <code>trim_character</code> is a single-character string literal or a character-valued input parameter (i.e., char or Character). If a trim specification is not provided, <b>BOTH</b> is assumed. The <b>TRIM</b> function returns the trimmed string.
+UPDATE=An update statement provide bulk operations over sets of entities.
+UPPER=The <b>UPPER</b> function converts a string to upper case and it returns a string.
+WHERE=The <b>WHERE</b> clause of a query consists of a conditional expression used to select objects or values that satisfy the expression. The <b>WHERE</b> clause restricts the result of a select statement or the scope of an update or delete operation.
+
+# JPA 2.0 identifiers
+CASE=A <b>CASE</b> expression can include any number of any number of <b>WHEN/THEN</b> statement pairs and returns one of the values in the map or the default item, evaluating the map key expressions to decide which.
+COALESCE=A <b>COALESCE</b> expression returns <code>null</code> if all its arguments evaluate to <code>null</code>, and the value of the first non-<code>null</code> argument otherwise.<p><p>The return type is the type returned by the arguments if they are all of the same type, otherwise it is undetermined.
+ENTRY=Use <b>ENTRY</b> in the <b>FROM</b> clause of a <b>MAP</b>. 
+INDEX=The <b>INDEX</b> function returns an integer value corresponding to the position of its argument in an ordered list. The <b>INDEX</b> function can only be applied to identification variables denoting types for which an order column has been specified.
+KEY=Use <b>KEY</b> in the <b>SELECT</b> clause or the <b>WHERE</b> clause of a <b>MAP</b>. 
+NULLIF=<b>NULLIF</b> returns the first expression if the two expressions are not equal. If the expressions are equal, <b>NULLIF</b> returns a null value of the type of the first expression.<p><p><b>NULLIF</b> is equivalent to a searched <b>CASE</b> expression in which the two expressions are equal and the resulting expression is <b>NULL</b>.<p><p>Returns the same type as the first expression.
+TYPE=An entity type expression can be used to restrict query polymorphism. The <b>TYPE</b> operator returns the exact type of the argument.
+VALUE=Use <b>VALUE</b> in the <b>SELECT</b> clause or the <b>WHERE</b> clause of a <b>MAP</b>. 
+
+# EclipseLink identifiers
+FUNC=Use <b>FUNC</b> for direct, native database functions.
+TREAT=<b>TREAT</b> downcasts child classes in inheritance hierarchy.
+
+# Reserved JPQL identifiers
+BIT_LENGTH=The identifier <b>BIT_LENGTH</b> is not currently used: it is reserved for future use.
+CHAR_LENGTH=The identifier <b>CHAR_LENGTH</b> is not currently used: it is reserved for future use.
+CHARACTER_LENGTH=The identifier <b>CHARACTER_LENGTH</b> is not currently used: it is reserved for future use.
+CLASS=The identifier <b>CLASS</b> is not currently used: it is reserved for future use.
+POSITION=The identifier <b>POSITION</b> is not currently used: it is reserved for future use.
+UNKNOWN=The identifier <b>UNKNOWN</b> is not currently used: it is reserved for future use.
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/property_files/jpt_ui_validation_preferences.properties b/jpa/plugins/org.eclipse.jpt.jpa.ui/property_files/jpt_ui_validation_preferences.properties
index 4886046..6e7f5c3 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/property_files/jpt_ui_validation_preferences.properties
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/property_files/jpt_ui_validation_preferences.properties
@@ -209,3 +209,4 @@
 ID_MAPPING_UNRESOLVED_GENERATOR_NAME=Unresolved generator name:
 GENERATED_VALUE_UNRESOLVED_GENERATOR=Generator is not defined in the persistence unit:
 QUERY_DUPLICATE_NAME=Duplicate query defined:
+JPQL_QUERY_VALIDATION=Invalid or incomplete JPQL queries:
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/JptJpaUiPlugin.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/JptJpaUiPlugin.java
index 6300e2e..0ca0e6a 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/JptJpaUiPlugin.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/JptJpaUiPlugin.java
@@ -54,6 +54,17 @@
 	private static final Object FOCUS_DATA = new Object();
 
 
+	// ********** Preference keys **********
+
+	/**
+	 * The preference key used to retrieve the case used for JPQL identifiers.
+	 */
+	public static final String JPQL_IDENTIFIER_CASE_PREF_KEY = PLUGIN_ID + ".jpqlIdentifier.case";
+	public static final String JPQL_IDENTIFIER_LOWERCASE_PREF_VALUE = "lowercase";
+	public static final String JPQL_IDENTIFIER_UPPERCASE_PREF_VALUE = "uppercase";
+	public static final String JPQL_IDENTIFIER_MATCH_FIRST_CHARACTER_CASE_PREF_KEY = PLUGIN_ID + ".jpqlIdentifier.matchFirstCharacterCase";
+
+
 	// ********** singleton **********
 
 	private static JptJpaUiPlugin INSTANCE;
@@ -117,9 +128,9 @@
 	 * Return an image for the specified <code>.gif<code>
 	 * file in the icons folder.
 	 */
-	//TODO we are using the ImageRegistry here and storing all our icons for the life of the plugin, 
-	//which means until the workspace is closed.  This is better than before where we constantly 
-	//created new images. Bug 306437 is about cleaning this up and using Local Resource Managers 
+	//TODO we are using the ImageRegistry here and storing all our icons for the life of the plugin,
+	//which means until the workspace is closed.  This is better than before where we constantly
+	//created new images. Bug 306437 is about cleaning this up and using Local Resource Managers
 	//on our views so that closing the JPA perspective would mean our icons are disposed.
 	public static Image getImage(String key) {
 		ImageRegistry imageRegistry = instance().getImageRegistry();
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JptUiIcons.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JptUiIcons.java
index 5b5a83c..843407c 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JptUiIcons.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JptUiIcons.java
@@ -124,4 +124,13 @@
 	public static final String TRANSIENT = "full/obj16/transient";
 	
 	public static final String NULL_ATTRIBUTE_MAPPING = "full/obj16/null-attribute-mapping";
-}
+
+
+	// **************** Content Assist icons **********************************
+
+	public static final String JPQL_FUNCTION = "full/obj16/jpql.function";
+
+	public static final String JPQL_IDENTIFIER = "full/obj16/jpql.identifier";
+
+	public static final String JPQL_VARIABLE = "full/obj16/jpql.variable";
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JptUiMessages.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JptUiMessages.java
index 19f4ea5..ab85011 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JptUiMessages.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JptUiMessages.java
@@ -92,6 +92,8 @@
 	public static String JpaFacetWizardPage_title;
 	public static String JpaFacetWizardPage_userLibsLink;
 	public static String JpaFacetWizardPage_userServerLibLabel;
+	public static String JpaJpqlJavaCompletionProposalComputer_Error;
+	public static String JpaJpqlSseCompletionProposalComputer_Error;
 	public static String JpaLibraryProviderInstallPanel_includeLibraries;
 	public static String JpaMakePersistentWizardPage_title;
 	public static String JpaMakePersistentWizardPage_message;
@@ -110,6 +112,7 @@
 	public static String JpaStructureView_linkWithEditorTooltip;
 	public static String JpaStructureView_structureNotAvailable;
 	public static String JpaStructureView_numItemsSelected;
+	public static String JpqlContentProposalProvider_Description;
 	public static String MappingFileWizard_title;
 	public static String MappingFileWizardPage_newFile_title;
 	public static String MappingFileWizardPage_newFile_desc;
@@ -132,7 +135,12 @@
 	public static String OverwriteConfirmerDialog_title;
 	public static String PersistenceItemLabelProviderFactory_persistenceLabel;
 	public static String EntitiesGenerator_jobName;
-	public static String JpaPreferencesPage_Description;
+	public static String JpaPreferencesPage_description;
+	public static String JpaPreferencesPage_jpqlEditor;
+	public static String JpaPreferencesPage_jpqlEditor_description;
+	public static String JpaPreferencesPage_jpqlEditor_lowerCaseRadioButton;
+	public static String JpaPreferencesPage_jpqlEditor_matchFirstCharacterCaseRadioButton;
+	public static String JpaPreferencesPage_jpqlEditor_upperCaseRadioButton;
 	public static String JpaProblemSeveritiesPage_Description;
 	public static String JpaProblemSeveritiesPage_Error;
 	public static String JpaProblemSeveritiesPage_Ignore;
@@ -140,7 +148,7 @@
 	public static String JpaProblemSeveritiesPage_Warning;
 	public static String SelectJpaOrmMappingFileDialog_newButton;
 
-	
+
 	private static final String BUNDLE_NAME = "jpt_ui"; //$NON-NLS-1$
 	private static final Class<?> BUNDLE_CLASS = JptUiMessages.class;
 	static {
@@ -150,5 +158,4 @@
 	private JptUiMessages() {
 		throw new UnsupportedOperationException();
 	}
-
-}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JptUiValidationPreferenceMessages.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JptUiValidationPreferenceMessages.java
index a9bfccf..aa39db0 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JptUiValidationPreferenceMessages.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/JptUiValidationPreferenceMessages.java
@@ -1,9 +1,9 @@
 /*******************************************************************************
- * Copyright (c) 2009, 2010 Oracle. All rights reserved.
+ * Copyright (c) 2009, 2011 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.
- * 
+ *
  * Contributors:
  *     Oracle - initial API and implementation
  ******************************************************************************/
@@ -19,9 +19,9 @@
 	public static String PROJECT_INVALID_CONNECTION;
 	public static String PROJECT_INACTIVE_CONNECTION;
 	public static String PROJECT_NO_PERSISTENCE_XML;
-	
+
 	public static String XML_VERSION_NOT_LATEST;
-	
+
 	public static String PROJECT_MULTIPLE_PERSISTENCE_XML;
 	public static String PERSISTENCE_NO_PERSISTENCE_UNIT;
 	public static String PERSISTENCE_MULTIPLE_PERSISTENCE_UNITS;
@@ -82,13 +82,13 @@
 	public static String ELEMENT_COLLECTION_TARGET_CLASS_NOT_DEFINED;
 	public static String ELEMENT_COLLECTION_TARGET_CLASS_MUST_BE_EMBEDDABLE_OR_BASIC_TYPE;
 	public static String ELEMENT_COLLECTION_MAP_KEY_CLASS_NOT_DEFINED;
-	
+
 	public static String DATABASE_CATEGORY;
 	public static String TABLE_CATEGORY;
 	public static String COLUMN_CATEGORY;
 	public static String OVERRIDES_CATEGORY;
 	public static String IMPLIED_ATTRIBUTE_LEVEL_CATEGORY;
-	
+
 	public static String TABLE_UNRESOLVED_CATALOG;
 	public static String TABLE_UNRESOLVED_SCHEMA;
 	public static String TABLE_UNRESOLVED_NAME;
@@ -125,12 +125,12 @@
 	public static String VIRTUAL_SECONDARY_TABLE_PRIMARY_KEY_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS;
 	public static String MAP_KEY_COLUMN_TABLE_NOT_VALID;
 	public static String VIRTUAL_MAP_KEY_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID;
-	
+
 	public static String COLLECTION_TABLE_UNRESOLVED_CATALOG;
 	public static String COLLECTION_TABLE_UNRESOLVED_SCHEMA;
 	public static String COLLECTION_TABLE_UNRESOLVED_NAME;
 	public static String ORDER_COLUMN_UNRESOLVED_NAME;
-	
+
 	public static String VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_CATALOG;
 	public static String VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_SCHEMA;
 	public static String VIRTUAL_ATTRIBUTE_JOIN_TABLE_UNRESOLVED_NAME;
@@ -170,7 +170,7 @@
 	public static String VIRTUAL_ATTRIBUTE_INVERSE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_JOIN_COLUMNS;
 	public static String VIRTUAL_ATTRIBUTE_MAP_KEY_COLUMN_TABLE_NOT_VALID;
 	public static String VIRTUAL_ATTRIBUTE_MAP_KEY_ATTRIBUTE_OVERRIDE_COLUMN_TABLE_NOT_VALID;
-	
+
 	public static String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_CATALOG;
 	public static String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_SCHEMA;
 	public static String VIRTUAL_ASSOCIATION_OVERRIDE_JOIN_TABLE_UNRESOLVED_NAME;
@@ -205,6 +205,7 @@
 	public static String ID_MAPPING_UNRESOLVED_GENERATOR_NAME;
 	public static String GENERATED_VALUE_UNRESOLVED_GENERATOR;
 	public static String QUERY_DUPLICATE_NAME;
+	public static String JPQL_QUERY_VALIDATION;
 
 	private static final String BUNDLE_NAME = "jpt_ui_validation_preferences"; //$NON-NLS-1$
 	private static final Class<?> BUNDLE_CLASS = JptUiValidationPreferenceMessages.class;
@@ -215,6 +216,4 @@
 	private JptUiValidationPreferenceMessages() {
 		throw new UnsupportedOperationException();
 	}
-
-
-}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/NamedQueryPropertyComposite.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/NamedQueryPropertyComposite.java
index 8c1fbb1..919b9b0 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/NamedQueryPropertyComposite.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/NamedQueryPropertyComposite.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2008, 2009 Oracle. All rights reserved.
+ * Copyright (c) 2008, 2011 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.
@@ -15,10 +15,11 @@
 import org.eclipse.jpt.common.utility.model.value.WritablePropertyValueModel;
 import org.eclipse.jpt.jpa.core.context.NamedQuery;
 import org.eclipse.jpt.jpa.core.context.Query;
+import org.eclipse.jpt.jpa.ui.internal.jpql.JpaJpqlContentProposalProvider;
 import org.eclipse.swt.widgets.Composite;
 
 /**
- * Here the layout of this pane:
+ * Here's the layout of this pane:
  * <pre>
  * -----------------------------------------------------------------------------
  * |        ------------------------------------------------------------------ |
@@ -40,11 +41,11 @@
  * @see NamedQueriesComposite - The parent container
  * @see QueryHintsComposite
  *
- * @version 2.0
- * @since 2.0
+ * @version 2.3
+ * @since 2.3
  */
-public class NamedQueryPropertyComposite<T extends NamedQuery> extends Pane<T>
-{
+public class NamedQueryPropertyComposite<T extends NamedQuery> extends Pane<T> {
+
 	/**
 	 * Creates a new <code>NamedQueryPropertyComposite</code>.
 	 *
@@ -59,6 +60,24 @@
 		super(parentPane, subjectHolder, parent);
 	}
 
+	protected WritablePropertyValueModel<String> buildNameTextHolder() {
+		return new PropertyAspectAdapter<NamedQuery, String>(
+				getSubjectHolder(), Query.NAME_PROPERTY) {
+			@Override
+			protected String buildValue_() {
+				return this.subject.getName();
+			}
+
+			@Override
+			protected void setValue_(String value) {
+				if (value.length() == 0) {
+					value = null;
+				}
+				this.subject.setName(value);
+			}
+		};
+	}
+
 	protected WritablePropertyValueModel<String> buildQueryHolder() {
 		return new PropertyAspectAdapter<NamedQuery, String>(getSubjectHolder(), Query.QUERY_PROPERTY) {
 			@Override
@@ -73,47 +92,49 @@
 		};
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	@Override
 	protected void initializeLayout(Composite container) {
-		
+
+		// Name widgets
 		addLabeledText(
-			container, 
-			JptUiDetailsMessages.NamedQueryComposite_nameTextLabel, 
+			container,
+			JptUiDetailsMessages.NamedQueryComposite_nameTextLabel,
 			buildNameTextHolder());
 
+		JpaJpqlContentProposalProvider provider = new JpaJpqlContentProposalProvider(
+			container,
+			getSubjectHolder(),
+			buildQueryHolder()
+		);
+
 		// Query text area
-		addLabeledMultiLineText(
+		Composite queryWidgets = this.addLabeledComposite(
 			container,
 			JptUiDetailsMessages.NamedQueryPropertyComposite_query,
-			buildQueryHolder(),
+			provider.getStyledText()
+		);
+
+		// Install the content assist icon at the top left of the StyledText.
+		// Note: For some reason, this needs to be done after the StyledText
+		//       is added to the labeled composite
+		provider.installControlDecoration();
+
+		adjustMultiLineTextLayout(
+			queryWidgets,
 			4,
-			null
+			provider.getStyledText(),
+			provider.getStyledText().getLineHeight()
 		);
 
 		// Query Hints pane
-		container = addTitledGroup(
+		container = this.addTitledGroup(
 			addSubPane(container, 5),
 			JptUiDetailsMessages.NamedQueryPropertyComposite_queryHintsGroupBox
 		);
 
 		new QueryHintsComposite(this, container);
 	}
-		
-	protected WritablePropertyValueModel<String> buildNameTextHolder() {
-		return new PropertyAspectAdapter<NamedQuery, String>(
-				getSubjectHolder(), Query.NAME_PROPERTY) {
-			@Override
-			protected String buildValue_() {
-				return this.subject.getName();
-			}
-		
-			@Override
-			protected void setValue_(String value) {
-				if (value.length() == 0) {
-					value = null;
-				}
-				this.subject.setName(value);
-			}
-		};
-	}
 }
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/QueriesComposite.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/QueriesComposite.java
index 6c3c949..cc6cc05 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/QueriesComposite.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/details/QueriesComposite.java
@@ -17,8 +17,8 @@
 import org.eclipse.jface.window.Window;
 import org.eclipse.jpt.common.ui.internal.util.ControlSwitcher;
 import org.eclipse.jpt.common.ui.internal.widgets.AddRemoveListPane;
-import org.eclipse.jpt.common.ui.internal.widgets.Pane;
 import org.eclipse.jpt.common.ui.internal.widgets.AddRemovePane.Adapter;
+import org.eclipse.jpt.common.ui.internal.widgets.Pane;
 import org.eclipse.jpt.common.utility.internal.CollectionTools;
 import org.eclipse.jpt.common.utility.internal.Transformer;
 import org.eclipse.jpt.common.utility.internal.model.value.CompositeListValueModel;
@@ -75,7 +75,7 @@
 {
 	private AddRemoveListPane<QueryContainer> listPane;
 	NamedNativeQueryPropertyComposite namedNativeQueryPane;
-	NamedQueryPropertyComposite<? extends NamedQuery> namedQueryPane;
+	Pane<? extends NamedQuery> namedQueryPane;
 	private WritablePropertyValueModel<Query> queryHolder;
 
 
@@ -295,7 +295,7 @@
 		installPaneSwitcher(pageBook);
 	}
 	
-	protected NamedQueryPropertyComposite<? extends NamedQuery> buildNamedQueryPropertyComposite(PageBook pageBook) {
+	protected Pane<? extends NamedQuery> buildNamedQueryPropertyComposite(PageBook pageBook) {
 		return new NamedQueryPropertyComposite<NamedQuery>(
 			this,
 			this.buildNamedQueryHolder(),
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpa2/details/NamedQueryProperty2_0Composite.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpa2/details/NamedQueryProperty2_0Composite.java
index 037037b..ef54324 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpa2/details/NamedQueryProperty2_0Composite.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpa2/details/NamedQueryProperty2_0Composite.java
@@ -1,27 +1,57 @@
 /*******************************************************************************
-* Copyright (c) 2009 Oracle. All rights reserved.
+* Copyright (c) 2009, 2011 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.
-* 
+*
 * Contributors:
 *     Oracle - initial API and implementation
 *******************************************************************************/
 package org.eclipse.jpt.jpa.ui.internal.jpa2.details;
 
 import org.eclipse.jpt.common.ui.internal.widgets.Pane;
+import org.eclipse.jpt.common.utility.internal.model.value.PropertyAspectAdapter;
 import org.eclipse.jpt.common.utility.model.value.PropertyValueModel;
+import org.eclipse.jpt.common.utility.model.value.WritablePropertyValueModel;
+import org.eclipse.jpt.jpa.core.context.Query;
 import org.eclipse.jpt.jpa.core.jpa2.context.NamedQuery2_0;
 import org.eclipse.jpt.jpa.ui.internal.details.JptUiDetailsMessages;
-import org.eclipse.jpt.jpa.ui.internal.details.NamedQueryPropertyComposite;
 import org.eclipse.jpt.jpa.ui.internal.details.QueryHintsComposite;
+import org.eclipse.jpt.jpa.ui.internal.jpql.JpaJpqlContentProposalProvider;
 import org.eclipse.swt.widgets.Composite;
 
 /**
- *  NamedQueryProperty2_0Composite
+ * Here's the layout of this pane:
+ * <pre>
+ * -----------------------------------------------------------------------------
+ * |            -------------------------------------------------------------- |
+ * | Query:     | I                                                          | |
+ * |            |                                                            | |
+ * |            |                                                            | |
+ * |            -------------------------------------------------------------- |
+ * |            -------------------------------------------------------------- |
+ * | Lock Mode: |                                                          |v| |
+ * |            -------------------------------------------------------------- |
+ * |                                                                           |
+ * | - Query Hints ----------------------------------------------------------- |
+ * | | --------------------------------------------------------------------- | |
+ * | | |                                                                   | | |
+ * | | | QueryHintsComposite                                               | | |
+ * | | |                                                                   | | |
+ * | | --------------------------------------------------------------------- | |
+ * | ------------------------------------------------------------------------- |
+ * -----------------------------------------------------------------------------</pre>
+ *
+ *
+ * @see NamedQuery2_0
+ * @see NamedQueriesComposite - The parent container
+ * @see QueryHintsComposite
+ *
+ * @version 2.0
+ * @since 2.0
  */
-public class NamedQueryProperty2_0Composite extends NamedQueryPropertyComposite<NamedQuery2_0>
-{
+public class NamedQueryProperty2_0Composite extends Pane<NamedQuery2_0> {
+
 	/**
 	 * Creates a new <code>NamedQueryProperty2_0Composite</code>.
 	 *
@@ -30,31 +60,83 @@
 	 * @param parent The parent container
 	 */
 	public NamedQueryProperty2_0Composite(Pane<?> parentPane,
-	                                   PropertyValueModel<NamedQuery2_0> subjectHolder,
-	                                   Composite parent) {
+	                                      PropertyValueModel<NamedQuery2_0> subjectHolder,
+	                                      Composite parent) {
 
 		super(parentPane, subjectHolder, parent);
 	}
 
+	protected WritablePropertyValueModel<String> buildNameTextHolder() {
+		return new PropertyAspectAdapter<NamedQuery2_0, String>(getSubjectHolder(), Query.NAME_PROPERTY) {
+			@Override
+			protected String buildValue_() {
+				return this.subject.getName();
+			}
+
+			@Override
+			protected void setValue_(String value) {
+				if (value.length() == 0) {
+					value = null;
+				}
+				this.subject.setName(value);
+			}
+		};
+	}
+
+	protected WritablePropertyValueModel<String> buildQueryHolder() {
+		return new PropertyAspectAdapter<NamedQuery2_0, String>(getSubjectHolder(), Query.QUERY_PROPERTY) {
+			@Override
+			protected String buildValue_() {
+				return this.subject.getQuery();
+			}
+
+			@Override
+			protected void setValue_(String value) {
+				this.subject.setQuery(value);
+			}
+		};
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
 	@Override
 	protected void initializeLayout(Composite container) {
-		
+
+		// Name widgets
 		this.addLabeledText(
-			container, 
-			JptUiDetailsMessages.NamedQueryComposite_nameTextLabel, 
+			container,
+			JptUiDetailsMessages.NamedQueryComposite_nameTextLabel,
 			this.buildNameTextHolder());
 
-		// Query text area
-		this.addLabeledMultiLineText(
+		JpaJpqlContentProposalProvider provider = new JpaJpqlContentProposalProvider(
 			container,
-			JptUiDetailsMessages.NamedQueryPropertyComposite_query,
-			this.buildQueryHolder(),
-			4,
-			null
+			getSubjectHolder(),
+			buildQueryHolder()
 		);
 
+		// Query text area
+		Composite queryWidgets = this.addLabeledComposite(
+			container,
+			JptUiDetailsMessages.NamedQueryPropertyComposite_query,
+			provider.getStyledText()
+		);
+
+		// Install the content assist icon at the top left of the StyledText.
+		// Note: For some reason, this needs to be done after the StyledText
+		//       is added to the labeled composite
+		provider.installControlDecoration();
+
+		adjustMultiLineTextLayout(
+			queryWidgets,
+			4,
+			provider.getStyledText(),
+			provider.getStyledText().getLineHeight()
+		);
+
+		// Lock Mode type
 		new LockModeComposite(this, container);
-			
+
 		// Query Hints pane
 		container = this.addTitledGroup(
 			this.addSubPane(container, 5),
@@ -63,5 +145,4 @@
 
 		new QueryHintsComposite(this, container);
 	}
-	
-}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpa2/details/Queries2_0Composite.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpa2/details/Queries2_0Composite.java
index 93d8139..17ead05 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpa2/details/Queries2_0Composite.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpa2/details/Queries2_0Composite.java
@@ -15,7 +15,6 @@
 import org.eclipse.jpt.jpa.core.context.Query;
 import org.eclipse.jpt.jpa.core.context.QueryContainer;
 import org.eclipse.jpt.jpa.core.jpa2.context.NamedQuery2_0;
-import org.eclipse.jpt.jpa.ui.internal.details.NamedQueryPropertyComposite;
 import org.eclipse.jpt.jpa.ui.internal.details.QueriesComposite;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.ui.part.PageBook;
@@ -34,9 +33,8 @@
 		super(parentPane, subjectHolder, parent);
 	}
 	
-	
 	@Override
-	protected NamedQueryPropertyComposite<NamedQuery2_0> buildNamedQueryPropertyComposite(PageBook pageBook) {
+	protected Pane<NamedQuery2_0> buildNamedQueryPropertyComposite(PageBook pageBook) {
 		return new NamedQueryProperty2_0Composite(
 			this,
 			this.buildNamedQuery2_0Holder(),
@@ -51,4 +49,4 @@
 			}
 		};
 	}
-}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlContentProposalProvider.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlContentProposalProvider.java
new file mode 100644
index 0000000..65f6087
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlContentProposalProvider.java
@@ -0,0 +1,698 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.ui.internal.jpql;
+
+import java.text.MessageFormat;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.commands.IHandler;
+import org.eclipse.core.commands.ParameterizedCommand;
+import org.eclipse.core.expressions.EvaluationResult;
+import org.eclipse.core.expressions.Expression;
+import org.eclipse.core.expressions.ExpressionInfo;
+import org.eclipse.core.expressions.IEvaluationContext;
+import org.eclipse.jface.bindings.Binding;
+import org.eclipse.jface.bindings.Trigger;
+import org.eclipse.jface.bindings.keys.KeyStroke;
+import org.eclipse.jface.bindings.keys.SWTKeySupport;
+import org.eclipse.jface.fieldassist.ControlDecoration;
+import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
+import org.eclipse.jface.internal.text.html.HTMLTextPresenter;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.DefaultInformationControl;
+import org.eclipse.jface.text.DefaultTextHover;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentListener;
+import org.eclipse.jface.text.IInformationControl;
+import org.eclipse.jface.text.IInformationControlCreator;
+import org.eclipse.jface.text.ITextHover;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Position;
+import org.eclipse.jface.text.contentassist.ContentAssistant;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
+import org.eclipse.jface.text.contentassist.IContentAssistant;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+import org.eclipse.jface.text.source.Annotation;
+import org.eclipse.jface.text.source.AnnotationModel;
+import org.eclipse.jface.text.source.DefaultAnnotationHover;
+import org.eclipse.jface.text.source.IAnnotationHover;
+import org.eclipse.jface.text.source.ISourceViewer;
+import org.eclipse.jface.text.source.SourceViewer;
+import org.eclipse.jface.text.source.SourceViewerConfiguration;
+import org.eclipse.jpt.common.ui.internal.listeners.SWTPropertyChangeListenerWrapper;
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.jpt.common.utility.model.event.PropertyChangeEvent;
+import org.eclipse.jpt.common.utility.model.listener.PropertyChangeListener;
+import org.eclipse.jpt.common.utility.model.value.PropertyValueModel;
+import org.eclipse.jpt.common.utility.model.value.WritablePropertyValueModel;
+import org.eclipse.jpt.jpa.core.JptJpaCorePlugin;
+import org.eclipse.jpt.jpa.core.context.NamedQuery;
+import org.eclipse.jpt.jpa.ui.internal.JptUiMessages;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.persistence.jpa.jpql.JPQLQueryProblem;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.FocusEvent;
+import org.eclipse.swt.events.FocusListener;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.ISources;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.editors.text.EditorsUI;
+import org.eclipse.ui.handlers.IHandlerActivation;
+import org.eclipse.ui.handlers.IHandlerService;
+import org.eclipse.ui.internal.editors.text.EditorsPlugin;
+import org.eclipse.ui.keys.IBindingService;
+import org.eclipse.ui.swt.IFocusService;
+import org.eclipse.ui.texteditor.AnnotationPreference;
+import org.eclipse.ui.texteditor.DefaultMarkerAnnotationAccess;
+import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
+import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
+
+/**
+ * This provider installs content assist support on a {@link StyledText} widget in order to give
+ * choices at any given position within a JPQL query.
+ * <p>
+ * TODO. Add syntax highlight for the JPQL identifiers.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+@SuppressWarnings({"nls", "restriction"})
+public final class JpaJpqlContentProposalProvider extends JpqlCompletionProposalComputer<ICompletionProposal> {
+
+	/**
+	 * This model holds onto the {@link Annotation annotations} that have been created for each
+	 * {@link JPQLQueryProblem}
+	 */
+	private AnnotationModel annotationModel;
+
+	/**
+	 * The decoration support required to paint the {@link Annotation annotations}, which are the
+	 * JPQL problems.
+	 */
+	private SourceViewerDecorationSupport decorationSupport;
+
+	/**
+	 * This handler will trigger an event that will be used to notify the {@link SourceViewer} to
+	 * invoke the content assist.
+	 */
+	private IHandlerActivation handlerActivation;
+
+	/**
+	 * The position within the JPQL query.
+	 */
+	private int position;
+
+	/**
+	 * The holder of the named query.
+	 */
+	private PropertyValueModel<? extends NamedQuery> queryHolder;
+
+	/**
+	 * The {@link ResourceBundle} that contains the JPQL problems.
+	 */
+	private ResourceBundle resourceBundle;
+
+	/**
+	 * This viewer is used to install various functionality over the {@link StyledText}.
+	 */
+	private SourceViewer sourceViewer;
+
+	/**
+	 * The configuration object used to configure the {@link SourceViewer}.
+	 */
+	private JpqlSourceViewerConfiguration sourceViewerConfiguration;
+
+	/**
+	 * The widget used to display the JPQL query.
+	 */
+	private StyledText styledText;
+
+	/**
+	 * This listener is used to dispose the {@link org.eclipse.persistence.jpa.jpql.JPQLQueryHelper
+	 * JPQLQueryHelper} when the subject changes and to reset the undo manager in order to prevent
+	 * the query from being entirely deleted with an undo.
+	 */
+	private PropertyChangeListener subjectChangeListener;
+
+	/**
+	 * The holder of the JPQL query.
+	 */
+	private WritablePropertyValueModel<String> textHolder;
+
+	/**
+	 * Listens to the JPQL query and keep the {@link Document} in sync.
+	 */
+	private PropertyChangeListener textListener;
+
+	/**
+	 * The unique identifier - appended by hashCode() - used to register the widget with the focus
+	 * handler.
+	 */
+	private static final String CONTROL_ID = "jpql.focus.control";
+
+	/**
+	 * The unique identifier used to mark an {@link Annotation} as a JPQL problem.
+	 */
+	private static final String ERROR_TYPE = "org.eclipse.jdt.ui.error";
+
+	/**
+	 * Creates a new <code>JpaJpqlContentProposalProvider</code>.
+	 *
+	 * @param parent The parent {@link Composite} where to add the JPQL query editor
+	 * @param queryHolder The holder of the named query
+	 * @param textHolder The holder of the JPQL query
+	 */
+	public JpaJpqlContentProposalProvider(Composite parent,
+	                                      PropertyValueModel<? extends NamedQuery> queryHolder,
+	                                      WritablePropertyValueModel<String> textHolder) {
+
+		super();
+		initialize(parent, queryHolder, textHolder);
+	}
+
+	private void activateHandler() {
+
+		IWorkbench workbench = PlatformUI.getWorkbench();
+		IFocusService focusService = (IFocusService) workbench.getService(IFocusService.class);
+		IHandlerService handlerService = (IHandlerService) workbench.getService(IHandlerService.class);
+
+		if ((focusService != null) && (handlerService != null)) {
+
+			focusService.addFocusTracker(styledText, CONTROL_ID + hashCode());
+
+			Expression expression = buildExpression();
+			IHandler handler = buildHandler();
+
+			handlerActivation = handlerService.activateHandler(
+				ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS,
+				handler,
+				expression
+			);
+
+			handlerActivation = handlerService.activateHandler(
+				ActionFactory.UNDO.getCommandId(),
+				handler,
+				expression
+			);
+
+			handlerActivation = handlerService.activateHandler(
+				ActionFactory.REDO.getCommandId(),
+				handler,
+				expression
+			);
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	private List<AnnotationPreference> annotationPreferences() {
+		return EditorsPlugin.getDefault().getMarkerAnnotationPreferences().getAnnotationPreferences();
+	}
+
+	private DisposeListener buildDisposeListener() {
+		return new DisposeListener() {
+			public void widgetDisposed(DisposeEvent e) {
+				dispose();
+			}
+		};
+	}
+
+	private IDocumentListener buildDocumentListener() {
+		return new IDocumentListener() {
+			public void documentAboutToBeChanged(DocumentEvent event) {
+			}
+			public void documentChanged(DocumentEvent event) {
+				try {
+					IDocument document = event.getDocument();
+					String text = document.get(0, document.getLength());
+					textHolder.setValue(text);
+				}
+				catch (BadLocationException e) {
+					// Simply ignore, should never happen
+				}
+			}
+		};
+	}
+
+	private Expression buildExpression() {
+		return new Expression() {
+			@Override
+			public void collectExpressionInfo(ExpressionInfo info) {
+				info.addVariableNameAccess(ISources.ACTIVE_FOCUS_CONTROL_NAME);
+			}
+			@Override
+			public EvaluationResult evaluate(IEvaluationContext context) {
+				Object variable = context.getVariable(ISources.ACTIVE_FOCUS_CONTROL_NAME);
+				return (variable == styledText) ? EvaluationResult.TRUE : EvaluationResult.FALSE;
+			}
+		};
+	}
+
+	private FocusListener buildFocusListener() {
+		return new FocusListener() {
+			public void focusGained(FocusEvent e) {
+			}
+			public void focusLost(FocusEvent e) {
+				// Only dispose the query helper if the content proposal popup doesn't grab the focus
+				if (!sourceViewerConfiguration.contentAssistant.hasProposalPopupFocus()) {
+					disposeQueryHelper();
+				}
+			}
+		};
+	}
+
+	private IHandler buildHandler() {
+		return new AbstractHandler() {
+			public Object execute(ExecutionEvent event) throws ExecutionException {
+				String commandId = event.getCommand().getId();
+
+				// Content Assist
+				if (ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS.equals(commandId)) {
+					sourceViewer.doOperation(ISourceViewer.CONTENTASSIST_PROPOSALS);
+				}
+				// Undo
+				else if (ActionFactory.UNDO.getCommandId().equals(commandId)) {
+					if (sourceViewer.getUndoManager().undoable()) {
+						sourceViewer.getUndoManager().undo();
+					}
+				}
+				// Redo
+				else if (ActionFactory.REDO.getCommandId().equals(commandId)) {
+					if (sourceViewer.getUndoManager().redoable()) {
+						sourceViewer.getUndoManager().redo();
+					}
+				}
+
+				return null;
+			}
+		};
+	}
+
+	private String buildMessage(JPQLQueryProblem problem) {
+		String message = resourceBundle().getString(problem.getMessageKey());
+		message = MessageFormat.format(message, (Object[]) problem.getMessageArguments());
+		return message;
+	}
+
+	private ModifyListener buildModifyListener() {
+		return new ModifyListener() {
+			public void modifyText(ModifyEvent e) {
+				validate();
+			}
+		};
+	}
+
+	private Comparator<JPQLQueryProblem> buildProblemComparator() {
+		return new Comparator<JPQLQueryProblem>() {
+			public int compare(JPQLQueryProblem problem1, JPQLQueryProblem problem2) {
+				int result = problem1.getStartPosition() - problem2.getStartPosition();
+				if (result == 0) {
+					result = problem1.getEndPosition() - problem2.getEndPosition();
+				}
+				return result;
+			}
+		};
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	ICompletionProposal buildProposal(String proposal,
+	                                  String displayString,
+	                                  String additionalInfo,
+	                                  Image image,
+	                                  int cursorOffset) {
+
+		return new JpqlCompletionProposal(
+			contentAssistProposals,
+			proposal,
+			displayString,
+			additionalInfo,
+			image,
+			namedQuery,
+			actualQuery,
+			jpqlQuery,
+			offset,
+			position,
+			cursorOffset,
+			false
+		);
+	}
+
+	private PropertyChangeListener buildSubjectChangeListener() {
+		return new PropertyChangeListener() {
+			public void propertyChanged(PropertyChangeEvent e) {
+				subjectChanged(e);
+			}
+		};
+	}
+
+	private PropertyChangeListener buildTextListener() {
+		return new SWTPropertyChangeListenerWrapper(new PropertyChangeListener() {
+			public void propertyChanged(PropertyChangeEvent event) {
+				String text = (String) event.getNewValue();
+				if (text == null) {
+					text = StringTools.EMPTY_STRING;
+				}
+				if (!styledText.getText().equals(text)) {
+					sourceViewer.getDocument().set(text);
+				}
+			}
+		});
+	}
+
+	private Image contentAssistImage() {
+		FieldDecorationRegistry registry = FieldDecorationRegistry.getDefault();
+		return registry.getFieldDecoration(FieldDecorationRegistry.DEC_CONTENT_PROPOSAL).getImage();
+	}
+
+	/**
+	 * Makes sure the {@link Color} used to paint the underlying problem is disposed when the
+	 * {@link StyledText} widget is disposed.
+	 */
+	private void dispose() {
+
+		sessionEnded();
+
+		decorationSupport.dispose();
+		textHolder.removePropertyChangeListener(PropertyValueModel.VALUE, textListener);
+		queryHolder.removePropertyChangeListener(PropertyValueModel.VALUE, subjectChangeListener);
+
+		IWorkbench workbench = PlatformUI.getWorkbench();
+		IHandlerService handlerService = (IHandlerService) workbench.getService(IHandlerService.class);
+		handlerService.deactivateHandler(handlerActivation);
+	}
+
+	private void disposeQueryHelper() {
+		queryHelper.dispose();
+		queryHelper.disposeProvider();
+	}
+
+	private KeyStroke findContentAssistTrigger() {
+
+		IBindingService bindingService = (IBindingService) PlatformUI.getWorkbench().getService(IBindingService.class);
+
+		// Dig through the list of available bindings to find the one for content assist
+		for (Binding binding : bindingService.getBindings()) {
+			if (isContentAssistBinding(binding)) {
+				Trigger[] triggers = binding.getTriggerSequence().getTriggers();
+				if ((triggers != null) && (triggers.length > 0)) {
+					return (KeyStroke) triggers[0];
+				}
+			}
+		}
+
+		// The default trigger was not found, use the default
+		return KeyStroke.getInstance(SWT.CTRL, ' ');
+	}
+
+	/**
+	 * Returns the widget used to display the JPQL query.
+	 *
+	 * @return The main widget
+	 */
+	public StyledText getStyledText() {
+		return styledText;
+	}
+
+	private void initialize(Composite parent,
+	                        PropertyValueModel<? extends NamedQuery> queryHolder,
+	                        WritablePropertyValueModel<String> textHolder) {
+
+		this.queryHolder     = queryHolder;
+		this.annotationModel = new AnnotationModel();
+		this.textHolder      = textHolder;
+
+		// Make sure the StyledText is kept in sync with the text holder
+		textListener = buildTextListener();
+		textHolder.addPropertyChangeListener(PropertyValueModel.VALUE, textListener);
+
+		// Make sure the user can't delete the entire query when doing undo
+		subjectChangeListener = buildSubjectChangeListener();
+		queryHolder.addPropertyChangeListener(PropertyValueModel.VALUE, subjectChangeListener);
+
+		// Create the SourceViewer, which is responsible for everything: content assist, tool tip
+		// hovering over the annotation (problems), etc
+		sourceViewer = new SourceViewer(parent, null, SWT.BORDER | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | SWT.H_SCROLL | SWT.FLAT);
+		sourceViewerConfiguration = new JpqlSourceViewerConfiguration();
+		sourceViewer.configure(sourceViewerConfiguration);
+		sourceViewer.setDocument(new Document(), annotationModel);
+		sourceViewer.getDocument().addDocumentListener(buildDocumentListener());
+
+		styledText = sourceViewer.getTextWidget();
+		styledText.addFocusListener(buildFocusListener());
+		styledText.addModifyListener(buildModifyListener());
+		styledText.addDisposeListener(buildDisposeListener());
+
+		// Add the support for painting the annotations (JPQL problems) in the source viewer
+		installDecorationSupport();
+
+		// Bind the content assist key trigger with the handler service
+		activateHandler();
+
+		// Install a custom context menu to the widget
+		TextTransferHandler.installContextMenu(styledText, sourceViewer.getUndoManager());
+	}
+
+	/**
+	 * Installs the content assist icon at the top left of the {@link StyledText}.
+	 */
+	public void installControlDecoration() {
+
+		// Retrieve the content assist trigger
+		KeyStroke contentAssistTrigger = findContentAssistTrigger();
+		String key = SWTKeySupport.getKeyFormatterForPlatform().format(contentAssistTrigger);
+
+		// Add the context assist icon at the top left corner of the StyledText
+		ControlDecoration decoration = new ControlDecoration(styledText, SWT.LEFT | SWT.TOP);
+		decoration.setDescriptionText(NLS.bind(JptUiMessages.JpqlContentProposalProvider_Description, key));
+		decoration.setImage(contentAssistImage());
+		decoration.setShowOnlyOnFocus(true);
+	}
+
+	private void installDecorationSupport() {
+
+		decorationSupport = new SourceViewerDecorationSupport(
+			sourceViewer,
+			null,
+			new DefaultMarkerAnnotationAccess(),
+			EditorsPlugin.getDefault().getSharedTextColors()
+		);
+
+		for (AnnotationPreference preference : annotationPreferences()) {
+			decorationSupport.setAnnotationPreference(preference);
+		}
+
+		decorationSupport.install(EditorsPlugin.getDefault().getPreferenceStore());
+	}
+
+	private boolean isContentAssistBinding(Binding binding) {
+
+		ParameterizedCommand command = binding.getParameterizedCommand();
+
+		return command != null &&
+		       command.getCommand() != null &&
+		       command.getCommand().getId().equals(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
+	}
+
+	private NamedQuery query() {
+		return queryHolder.getValue();
+	}
+
+	private ResourceBundle resourceBundle() {
+		if (resourceBundle == null) {
+			resourceBundle = ResourceBundle.getBundle(
+				"jpa_jpql_validation",
+				Locale.getDefault(),
+				JptJpaCorePlugin.class.getClassLoader()
+			);
+		}
+		return resourceBundle;
+	}
+
+	private List<JPQLQueryProblem> sortProblems(List<JPQLQueryProblem> problems) {
+		Collections.sort(problems, buildProblemComparator());
+		return problems;
+	}
+
+	private void subjectChanged(PropertyChangeEvent e) {
+
+		// Disposes of the internal data since the subject changed
+		disposeQueryHelper();
+
+		// Prevent undoing the actual query that was set
+		if (e.getNewValue() != null) {
+			sourceViewer.getUndoManager().reset();
+		}
+	}
+
+	/**
+	 * Validates the given JPQL query and add highlights where problems have been found.
+	 */
+	private void validate() {
+
+		NamedQuery query = query();
+		annotationModel.removeAllAnnotations();
+
+		if ((query != null) && !styledText.isDisposed()) {
+			try {
+				String jpqlQuery = styledText.getText();
+				queryHelper.setQuery(query, jpqlQuery);
+				String parsedJpqlQuery = queryHelper.getParsedJPQLQuery();
+
+				for (JPQLQueryProblem problem : sortProblems(queryHelper.validate())) {
+
+					// Create the range
+					int[] positions = queryHelper.buildPositions(problem, parsedJpqlQuery, jpqlQuery);
+
+					// Add the problem to the tool tip
+					Annotation annotation = new Annotation(ERROR_TYPE, true, buildMessage(problem));
+					annotationModel.addAnnotation(annotation, new Position(positions[0], positions[1] - positions[0]));
+				}
+			}
+			finally {
+				queryHelper.dispose();
+			}
+		}
+	}
+
+	/**
+	 * This processor is responsible to create the list of {@link ICompletionProposal proposals}
+	 * based on the position of the cursor within the query.
+	 */
+	private class ContentAssistProcessor implements IContentAssistProcessor {
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {
+
+			JpaJpqlContentProposalProvider.this.position = offset;
+
+			String jpqlQuery = viewer.getDocument().get();
+			List<ICompletionProposal> proposals = buildProposals(query(), jpqlQuery, 0, position);
+			return proposals.toArray(new ICompletionProposal[proposals.size()]);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {
+			return null;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public char[] getCompletionProposalAutoActivationCharacters() {
+			return null;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public char[] getContextInformationAutoActivationCharacters() {
+			return null;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public IContextInformationValidator getContextInformationValidator() {
+			return null;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		public String getErrorMessage() {
+			return null;
+		}
+	}
+
+	private class JpqlSourceViewerConfiguration extends SourceViewerConfiguration {
+
+		/**
+		 * Keeps track of the content assist since we need to know when the popup is opened or not.
+		 */
+		ContentAssistant contentAssistant;
+
+		private IInformationControlCreator buildInformationControlCreator() {
+			return new IInformationControlCreator() {
+				public IInformationControl createInformationControl(Shell parent) {
+					return new DefaultInformationControl(
+						parent,
+						EditorsUI.getTooltipAffordanceString(),
+						new HTMLTextPresenter(true)
+					);
+				}
+			};
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public IAnnotationHover getAnnotationHover(ISourceViewer sourceViewer) {
+			return new DefaultAnnotationHover();
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
+			contentAssistant = new ContentAssistant();
+			contentAssistant.setContentAssistProcessor(new ContentAssistProcessor(), IDocument.DEFAULT_CONTENT_TYPE);
+			contentAssistant.setInformationControlCreator(buildInformationControlCreator());
+			return contentAssistant;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType) {
+			return new DefaultTextHover(sourceViewer);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 */
+		@Override
+		public ITextHover getTextHover(ISourceViewer sourceViewer, String contentType, int stateMask) {
+			return new DefaultTextHover(sourceViewer);
+		}
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlJavaCompletionProposalComputer.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlJavaCompletionProposalComputer.java
new file mode 100644
index 0000000..fa60974
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlJavaCompletionProposalComputer.java
@@ -0,0 +1,320 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.ui.internal.jpql;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jdt.core.CompletionContext;
+import org.eclipse.jdt.core.ICompilationUnit;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
+import org.eclipse.jdt.core.dom.Annotation;
+import org.eclipse.jdt.core.dom.ArrayInitializer;
+import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.IExtendedModifier;
+import org.eclipse.jdt.core.dom.MemberValuePair;
+import org.eclipse.jdt.core.dom.NormalAnnotation;
+import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
+import org.eclipse.jdt.core.dom.StringLiteral;
+import org.eclipse.jdt.ui.text.java.ContentAssistInvocationContext;
+import org.eclipse.jdt.ui.text.java.IJavaCompletionProposalComputer;
+import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jpt.common.core.internal.utility.jdt.ASTTools;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.jpt.jpa.core.JpaFile;
+import org.eclipse.jpt.jpa.core.JpaStructureNode;
+import org.eclipse.jpt.jpa.core.JptJpaCorePlugin;
+import org.eclipse.jpt.jpa.core.context.NamedQuery;
+import org.eclipse.jpt.jpa.core.context.java.JavaEntity;
+import org.eclipse.jpt.jpa.core.context.java.JavaNamedQuery;
+import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType;
+import org.eclipse.jpt.jpa.core.context.java.JavaTypeMapping;
+import org.eclipse.jpt.jpa.ui.JptJpaUiPlugin;
+import org.eclipse.jpt.jpa.ui.internal.JptUiMessages;
+import org.eclipse.persistence.jpa.jpql.ExpressionTools;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * This computer adds content assist support when it is invoked inside the query element of {@link
+ * javax.persistence.NamedQuery &#64;NamedQuery}.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+@SuppressWarnings("restriction")
+public final class JpaJpqlJavaCompletionProposalComputer extends JpqlCompletionProposalComputer<ICompletionProposal>
+                                                         implements IJavaCompletionProposalComputer {
+
+	/**
+	 * Creates a new <code>JpaJpqlJavaCompletionProposalComputer</code>.
+	 */
+	public JpaJpqlJavaCompletionProposalComputer() {
+		super();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	ICompletionProposal buildProposal(String proposal,
+	                                  String displayString,
+	                                  String additionalInfo,
+	                                  Image image,
+	                                  int cursorOffset) {
+
+		return new JpqlCompletionProposal(
+			contentAssistProposals,
+			proposal,
+			displayString,
+			additionalInfo,
+			image,
+			namedQuery,
+			actualQuery,
+			jpqlQuery,
+			offset + 1, // +1 is to skip the opening "
+			position,
+			cursorOffset,
+			true
+		);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public List<ICompletionProposal> computeCompletionProposals(ContentAssistInvocationContext context,
+	                                                            IProgressMonitor monitor) {
+
+		if (context instanceof JavaContentAssistInvocationContext) {
+			monitor.beginTask(null, 100);
+			try {
+				return computeCompletionProposals((JavaContentAssistInvocationContext) context, monitor);
+			}
+			catch (Exception e) {
+				Status status = new Status(IStatus.ERROR, JptJpaUiPlugin.PLUGIN_ID, JptUiMessages.JpaJpqlJavaCompletionProposalComputer_Error, e);
+				JptJpaCorePlugin.log(status);
+			}
+			finally {
+				monitor.done();
+			}
+		}
+
+		return Collections.emptyList();
+	}
+
+	private List<ICompletionProposal> computeCompletionProposals(JavaContentAssistInvocationContext context,
+	                                                             IProgressMonitor monitor) throws Exception {
+
+		CompletionContext completionContext = context.getCoreContext();
+
+		// The token "start" is the offset of the token's first character within the document.
+		// A token start of -1 can means:
+		// - It is inside the string representation of a unicode character, \\u0|0E9 where | is the
+		//   cursor, then -1 is returned;
+		// - The string is not valid (it has some invalid characters)
+		int tokenStart = completionContext.getTokenStart();
+		if (tokenStart == -1) return Collections.emptyList();
+
+		int[] position = { completionContext.getOffset() - tokenStart - 1 };
+		if (position[0] < 0) return Collections.emptyList();
+
+		ICompilationUnit compilationUnit = context.getCompilationUnit();
+		if (compilationUnit == null) return Collections.emptyList();
+		CompilationUnit astRoot = ASTTools.buildASTRoot(compilationUnit);
+
+		IFile file = getCorrespondingResource(compilationUnit);
+		if (file == null) return Collections.emptyList();
+
+		JpaFile jpaFile = JptJpaCorePlugin.getJpaFile(file);
+		if (jpaFile == null) return Collections.emptyList();
+
+		monitor.worked(80);
+		checkCanceled(monitor);
+
+		// Retrieve the JPA's model object
+		NamedQuery namedQuery = namedQuery(astRoot, jpaFile, tokenStart);
+		if (namedQuery == null) return Collections.emptyList();
+
+		// Retrieve the actual value of the element "query" since the content assist can be
+		// invoked before the model received the new content
+		String jpqlQuery = jpqlQuery(astRoot, tokenStart, completionContext.getTokenEnd(), position);
+
+		// Now create the proposals
+		return buildProposals(namedQuery, jpqlQuery, tokenStart, position[0]);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public List<IContextInformation> computeContextInformation(ContentAssistInvocationContext context,
+	                                                           IProgressMonitor monitor) {
+
+		return Collections.emptyList();
+	}
+
+	private NamedQuery findNamedQuery(JpaStructureNode structureNode,
+	                                  CompilationUnit astRoot,
+	                                  int tokenStart) {
+
+		if (structureNode instanceof JavaPersistentType) {
+			JavaPersistentType persistentType = (JavaPersistentType) structureNode;
+			JavaTypeMapping typeMapping = persistentType.getMapping();
+
+			if (typeMapping instanceof JavaEntity) {
+				JavaEntity entity = (JavaEntity) typeMapping;
+
+				for (Iterator<JavaNamedQuery> queries = entity.getQueryContainer().namedQueries(); queries.hasNext(); ) {
+					JavaNamedQuery namedQuery = queries.next();
+					TextRange textRange = namedQuery.getQueryAnnotation().getQueryTextRange(astRoot);
+
+					if ((textRange != null) && textRange.includes(tokenStart)) {
+						return namedQuery;
+					}
+				}
+			}
+		}
+
+		return null;
+	}
+
+	private IFile getCorrespondingResource(ICompilationUnit compilationUnit) {
+		try {
+			return (IFile) compilationUnit.getCorrespondingResource();
+		}
+		catch (JavaModelException ex) {
+			JptJpaCorePlugin.log(ex);
+			return null;
+		}
+	}
+
+	private boolean isInsideNode(ASTNode node, int tokenStart, int tokenEnd) {
+		int startPosition = node.getStartPosition();
+		return startPosition <= tokenStart &&
+		       startPosition + node.getLength() >= tokenEnd;
+	}
+
+	private String jpqlQuery(CompilationUnit astRoot, int tokenStart, int tokenEnd, int[] position) {
+
+		String jpqlQuery = retrieveQuery(astRoot, tokenStart, tokenEnd);
+
+		if (jpqlQuery == null) {
+			jpqlQuery = StringTools.EMPTY_STRING;
+		}
+		else if (StringTools.stringIsQuoted(jpqlQuery)) {
+			jpqlQuery = jpqlQuery.substring(1, jpqlQuery.length() - 1);
+		}
+
+		return jpqlQuery;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	String modifyJpqlQuery(String jpqlQuery, int[] position) {
+		return ExpressionTools.unescape(jpqlQuery, position);
+	}
+
+	private NamedQuery namedQuery(CompilationUnit astRoot, JpaFile jpaFile, int tokenStart) {
+
+		for (JpaStructureNode node : jpaFile.getRootStructureNodes()) {
+			NamedQuery namedQuery = findNamedQuery(node, astRoot, tokenStart);
+			if (namedQuery != null) {
+				return namedQuery;
+			}
+		}
+
+		return null;
+	}
+
+	/**
+	 * This twisted code is meant to retrieve the real string value that is not escaped and to also
+	 * retrieve the position within the non-escaped string. The query could have escape characters,
+	 * such as \r, \n etc being written as \\r, \\n, the position is based on that escaped string,
+	 * the conversion will convert them into \r and \r and adjust the position accordingly.
+	 *
+	 * @param astRoot The parsed tree representation of the Java source file
+	 * @param tokenStart The beginning of the query expression of the {@link javax.persistence.NamedQuery
+	 * &#64;NamedQuery}'s query member within the source file
+	 * @param tokenEnd The end of the query member within the source file
+	 * @param position The position of the cursor within the query expression
+	 * @return The actual value retrieved from the query element
+	 */
+	@SuppressWarnings("unchecked")
+	private String retrieveQuery(CompilationUnit astRoot, int tokenStart, int tokenEnd) {
+
+		// Dig into the TypeDeclarations
+		for (AbstractTypeDeclaration type : (List<AbstractTypeDeclaration>) astRoot.types()) {
+
+			if (isInsideNode(type, tokenStart, tokenEnd)) {
+
+				// Dig inside its modifiers and annotations
+				for (IExtendedModifier modifier : (List<IExtendedModifier>) type.modifiers()) {
+
+					if (!modifier.isAnnotation()) {
+						continue;
+					}
+
+					Annotation annotation = (Annotation) modifier;
+
+					// Dig inside the annotation
+					if (isInsideNode(annotation, tokenStart, tokenEnd)) {
+
+						// @NamedQueries({...})
+						if (annotation.isSingleMemberAnnotation()) {
+							SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) annotation;
+							ArrayInitializer array = (ArrayInitializer) singleMemberAnnotation.getValue();
+
+							for (org.eclipse.jdt.core.dom.Expression expression : (List<org.eclipse.jdt.core.dom.Expression>) array.expressions()) {
+								if (isInsideNode(expression, tokenStart, tokenEnd)) {
+									return retrieveQuery((NormalAnnotation) expression, tokenStart, tokenEnd);
+								}
+							}
+						}
+						// @NamedQuery()
+						else if (annotation.isNormalAnnotation()) {
+							return retrieveQuery((NormalAnnotation) annotation, tokenStart, tokenEnd);
+						}
+					}
+				}
+			}
+		}
+
+		return null;
+	}
+
+	@SuppressWarnings("unchecked")
+	private String retrieveQuery(NormalAnnotation annotation, int tokenStart, int tokenEnd) {
+
+		for (MemberValuePair pair : (List<MemberValuePair>) annotation.values()) {
+			org.eclipse.jdt.core.dom.Expression expression = pair.getValue();
+
+			if (isInsideNode(expression, tokenStart, tokenEnd)) {
+				StringLiteral literal = (StringLiteral) pair.getValue();
+				return literal.getEscapedValue();
+			}
+		}
+
+		return null;
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlSseCompletionProposalComputer.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlSseCompletionProposalComputer.java
new file mode 100644
index 0000000..6fab382
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpaJpqlSseCompletionProposalComputer.java
@@ -0,0 +1,224 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.ui.internal.jpql;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.eclipse.core.filebuffers.FileBuffers;
+import org.eclipse.core.filebuffers.ITextFileBuffer;
+import org.eclipse.core.filebuffers.ITextFileBufferManager;
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jpt.common.core.utility.TextRange;
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.jpt.jpa.core.JpaFile;
+import org.eclipse.jpt.jpa.core.JpaStructureNode;
+import org.eclipse.jpt.jpa.core.JptJpaCorePlugin;
+import org.eclipse.jpt.jpa.core.context.PersistentType;
+import org.eclipse.jpt.jpa.core.context.QueryContainer;
+import org.eclipse.jpt.jpa.core.context.TypeMapping;
+import org.eclipse.jpt.jpa.core.context.orm.EntityMappings;
+import org.eclipse.jpt.jpa.core.context.orm.OrmEntity;
+import org.eclipse.jpt.jpa.core.context.orm.OrmNamedQuery;
+import org.eclipse.jpt.jpa.ui.JptJpaUiPlugin;
+import org.eclipse.jpt.jpa.ui.internal.JptUiMessages;
+import org.eclipse.persistence.jpa.jpql.ExpressionTools;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext;
+import org.eclipse.wst.sse.ui.contentassist.ICompletionProposalComputer;
+
+/**
+ * This computer adds content assist support when it is invoked inside the &lt;query&gt; element
+ * defined in a mapping file (ORM Configuration).
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+public final class JpaJpqlSseCompletionProposalComputer extends JpqlCompletionProposalComputer<ICompletionProposal>
+                                                        implements ICompletionProposalComputer {
+
+	/**
+	 * Creates a new <code>JpaJpqlSseCompletionProposalComputer</code>.
+	 */
+	public JpaJpqlSseCompletionProposalComputer() {
+		super();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	ICompletionProposal buildProposal(String proposal,
+	                                  String displayString,
+	                                  String additionalInfo,
+	                                  Image image,
+	                                  int cursorOffset) {
+
+		return new JpqlCompletionProposal(
+			contentAssistProposals,
+			proposal,
+			displayString,
+			additionalInfo,
+			image,
+			namedQuery,
+			actualQuery,
+			jpqlQuery,
+			offset,
+			position,
+			cursorOffset,
+			true
+		);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public List<ICompletionProposal> computeCompletionProposals(CompletionProposalInvocationContext context,
+	                                                            IProgressMonitor monitor) {
+
+		monitor.beginTask(null, 100);
+
+		try {
+			int offset = context.getInvocationOffset();
+			if (offset == -1) return Collections.emptyList();
+
+			ITextFileBufferManager manager = FileBuffers.getTextFileBufferManager();
+			ITextFileBuffer buffer = manager.getTextFileBuffer(context.getDocument());
+			if (buffer == null) return Collections.emptyList();
+
+			IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
+			IFile file = root.getFile(buffer.getLocation());
+
+			JpaFile jpaFile = JptJpaCorePlugin.getJpaFile(file);
+			if (jpaFile == null) return Collections.emptyList();
+
+			monitor.worked(80);
+			checkCanceled(monitor);
+
+			// Retrieve the JPA's model object
+			int[] position = new int[1];
+			OrmNamedQuery namedQuery = namedQuery(jpaFile, offset, position);
+			if (namedQuery == null) return Collections.emptyList();
+
+			// Keep track of the beginning of the text since the entire string is always replaced
+			int tokenStart = offset - position[0];
+
+			// Now create the proposals
+			String jpqlQuery = jpqlQuery(namedQuery, context.getDocument());
+			return buildProposals(namedQuery, jpqlQuery, tokenStart, position[0]);
+		}
+		catch (Exception e) {
+			Status status = new Status(IStatus.ERROR, JptJpaUiPlugin.PLUGIN_ID, JptUiMessages.JpaJpqlSseCompletionProposalComputer_Error, e);
+			JptJpaCorePlugin.log(status);
+		}
+		finally {
+			monitor.done();
+		}
+
+		return Collections.emptyList();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public List<IContextInformation> computeContextInformation(CompletionProposalInvocationContext context,
+	                                                           IProgressMonitor monitor) {
+
+		return Collections.emptyList();
+	}
+
+	private OrmNamedQuery findNamedQuery(JpaStructureNode structureNode, int offset, int[] position) {
+
+		if (structureNode instanceof EntityMappings) {
+			EntityMappings entityMappings = (EntityMappings) structureNode;
+
+			// First look into the global queries
+			OrmNamedQuery query = findNamedQuery(entityMappings.getQueryContainer(), offset, position);
+
+			// Now traverse each entity
+			if (query != null) {
+				return query;
+			}
+
+			for (PersistentType persistentType : entityMappings.getPersistentTypes()) {
+				TypeMapping typeMapping = persistentType.getMapping();
+
+				if (typeMapping instanceof OrmEntity) {
+					query = findNamedQuery(((OrmEntity) typeMapping).getQueryContainer(), offset, position);
+
+					if (query != null) {
+						return query;
+					}
+				}
+			}
+		}
+
+		return null;
+	}
+
+	private OrmNamedQuery findNamedQuery(QueryContainer container, int offset, int[] position) {
+
+		for (Iterator<OrmNamedQuery> queries = container.namedQueries(); queries.hasNext(); ) {
+			OrmNamedQuery namedQuery = queries.next();
+			TextRange textRange = namedQuery.getQueryTextRange();
+
+			if (textRange.touches(offset)) {
+				position[0] = offset - textRange.getOffset();
+				return namedQuery;
+			}
+		}
+
+		return null;
+	}
+
+	private String jpqlQuery(OrmNamedQuery namedQuery, IDocument document) {
+		try {
+			TextRange range = namedQuery.getQueryTextRange();
+			return document.get(range.getOffset(), range.getLength());
+		}
+		catch (BadLocationException e) {
+			return StringTools.EMPTY_STRING;
+		}
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	String modifyJpqlQuery(String jpqlQuery, int[] position) {
+		return ExpressionTools.unescape(jpqlQuery, position);
+	}
+
+	private OrmNamedQuery namedQuery(JpaFile jpaFile, int offset, int[] position) {
+
+		for (JpaStructureNode node : jpaFile.getRootStructureNodes()) {
+			OrmNamedQuery namedQuery = findNamedQuery(node, offset, position);
+			if (namedQuery != null) {
+				return namedQuery;
+			}
+		}
+
+		return null;
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlCompletionProposal.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlCompletionProposal.java
new file mode 100644
index 0000000..aefd14b
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlCompletionProposal.java
@@ -0,0 +1,158 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.ui.internal.jpql;
+
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.ui.PreferenceConstants;
+import org.eclipse.jface.text.BadLocationException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jpt.jpa.core.context.NamedQuery;
+import org.eclipse.persistence.jpa.jpql.ContentAssistProposals;
+import org.eclipse.persistence.jpa.jpql.ResultQuery;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+
+/**
+ * The concrete implementation of a {@link org.eclipse.jface.text.contentassist.ICompletionProposal
+ * ICompletionProposal} that adds relevance and toggling the completion insertion property behavior.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+final class JpqlCompletionProposal implements ICompletionProposal {
+
+	private String actualQuery;
+	private String additionalInfo;
+	private ContentAssistProposals proposals;
+	private int cursorOffset;
+	private String displayString;
+	private boolean escapeCharacters;
+	private Image image;
+	private String jpqlQuery;
+	private NamedQuery namedQuery;
+	private int offset;
+	private int position;
+	private String proposal;
+	private ResultQuery result;
+	private boolean toggleCompletion;
+
+	JpqlCompletionProposal(ContentAssistProposals proposals,
+	                       String proposal,
+	                       String displayString,
+	                       String additionalInfo,
+	                       Image image,
+	                       NamedQuery namedQuery,
+	                       String actualQuery,
+	                       String jpqlQuery,
+	                       int offset,
+	                       int position,
+	                       int cursorOffset,
+	                       boolean escapeCharacters) {
+
+		super();
+
+		this.image            = image;
+		this.offset           = offset;
+		this.position         = position;
+		this.proposal         = proposal;
+		this.jpqlQuery        = jpqlQuery;
+		this.proposals        = proposals;
+		this.namedQuery       = namedQuery;
+		this.actualQuery      = actualQuery;
+		this.cursorOffset     = cursorOffset;
+		this.displayString    = displayString;
+		this.additionalInfo   = additionalInfo;
+		this.escapeCharacters = escapeCharacters;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public void apply(IDocument document) {
+		try {
+			ResultQuery result = buildResult();
+			document.replace(offset, actualQuery.length(), result.getQuery());
+		}
+		catch (BadLocationException e) {
+			// Ignore
+		}
+	}
+
+	private ResultQuery buildResult() {
+		if (result == null) {
+			if (escapeCharacters) {
+				result = proposals.buildEscapedQuery(
+					jpqlQuery,
+					proposal,
+					position,
+					isCompletionInserts() ^ toggleCompletion
+				);
+			}
+			else {
+				result = proposals.buildQuery(
+					jpqlQuery,
+					proposal,
+					position,
+					isCompletionInserts() ^ toggleCompletion
+				);
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String getAdditionalProposalInfo() {
+		return additionalInfo;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public IContextInformation getContextInformation() {
+		return null; // Not needed, this is legacy API
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public String getDisplayString() {
+		return displayString;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Image getImage() {
+		return image;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	public Point getSelection(IDocument document) {
+		ResultQuery result = buildResult();
+		return new Point(offset + result.getPosition() + cursorOffset, 0);
+	}
+
+	private boolean isCompletionInserts() {
+		IJavaProject javaProject = namedQuery.getJpaProject().getJavaProject();
+		String value = PreferenceConstants.getPreference(PreferenceConstants.CODEASSIST_INSERT_COMPLETION, javaProject);
+		return Boolean.valueOf(value);
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlCompletionProposalComputer.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlCompletionProposalComputer.java
new file mode 100644
index 0000000..a6afab7
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlCompletionProposalComputer.java
@@ -0,0 +1,437 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.ui.internal.jpql;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.jpt.common.utility.internal.CollectionTools;
+import org.eclipse.jpt.jpa.core.context.NamedQuery;
+import org.eclipse.jpt.jpa.core.internal.jpql.JpaJpqlQueryHelper;
+import org.eclipse.jpt.jpa.ui.JptJpaUiPlugin;
+import org.eclipse.jpt.jpa.ui.internal.JptUiIcons;
+import org.eclipse.persistence.jpa.internal.jpql.WordParser;
+import org.eclipse.persistence.jpa.internal.jpql.parser.Expression;
+import org.eclipse.persistence.jpa.internal.jpql.parser.IdentifierRole;
+import org.eclipse.persistence.jpa.internal.jpql.parser.JPQLExpression;
+import org.eclipse.persistence.jpa.jpql.ContentAssistProposals;
+import org.eclipse.persistence.jpa.jpql.spi.IEntity;
+import org.eclipse.persistence.jpa.jpql.spi.IMapping;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.widgets.Display;
+
+import static org.eclipse.jpt.common.utility.internal.CollectionTools.*;
+
+/**
+ * The abstract definition of JPQL content assist support.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+@SuppressWarnings({"nls", "restriction"})
+abstract class JpqlCompletionProposalComputer<T> {
+
+	/**
+	 * The current value of the query element.
+	 */
+	String actualQuery;
+
+	/**
+	 * The provider of content assist items based on the position of the cursor within the JPQL query.
+	 */
+	ContentAssistProposals contentAssistProposals;
+
+	/**
+	 * The local registry containing the images used to display the possible proposals. The registry is
+	 * disposed when the session ended.
+	 */
+	private ImageRegistry imageRegistry;
+
+	/**
+	 * The same value as {@link #actualQuery} or the modified query that was used by the Hermes parser.
+	 */
+	String jpqlQuery;
+
+	/**
+	 * The JPA model object that is used to access the Java project.
+	 */
+	NamedQuery namedQuery;
+
+	/**
+	 * The start position of the query within the document.
+	 */
+	int offset;
+
+	/**
+	 *
+	 */
+	private String partialWord;
+
+	/**
+	 * The position of the cursor within {@link #actualQuery}.
+	 */
+	int position;
+
+	/**
+	 * This helper is responsible to retrieve the possible proposals to complete or to add more
+	 * information to a JPQL based on the position of the cursor.
+	 */
+	final JpaJpqlQueryHelper queryHelper;
+
+	/**
+	 * Creates a new <code>JpqlCompletionProposalComputer</code>.
+	 */
+	public JpqlCompletionProposalComputer() {
+		super();
+		queryHelper = new JpaJpqlQueryHelper();
+	}
+
+	/**
+	 * Adds completion proposals for the abstract schema names that are possible proposals.
+	 *
+	 * @param proposals The list used to store the new completion proposals
+	 */
+	private void addAbstractSchemaNames(List<T> proposals) {
+		for (IEntity abstractSchemaType : sortByNames(contentAssistProposals.abstractSchemaTypes())) {
+			proposals.add(buildAbstractSchemaNameProposal(abstractSchemaType));
+		}
+	}
+
+	/**
+	 * Adds completion proposals for the identification variables that are possible proposals.
+	 *
+	 * @param proposals The list used to store the new completion proposals
+	 */
+	private void addIdentificationVariables(List<T> proposals) {
+		for (String variable : sort(contentAssistProposals.identificationVariables())) {
+			proposals.add(buildIdentificationVariableProposal(variable));
+		}
+	}
+
+	/**
+	 * Adds completion proposals for the JPQL identifiers that are possible proposals.
+	 *
+	 * @param proposals The list used to store the new completion proposals
+	 */
+	private void addIdentifiers(List<T> proposals) {
+		for (String identifier : sort(contentAssistProposals.identifiers())) {
+			proposals.add(buildIdentifierProposal(identifier));
+		}
+	}
+
+	private String additionalInfo(String proposal) {
+		return JpqlIdentifierMessages.localizedMessage(proposal);
+	}
+
+	/**
+	 * Adds completion proposals for the state fields and association fields that are possible proposals.
+	 *
+	 * @param proposals The list used to store the new completion proposals
+	 */
+	private void addMappings(List<T> proposals) {
+		for (IMapping mapping : sort(contentAssistProposals.mappings())) {
+			proposals.add(buildMappingProposal(mapping));
+		}
+	}
+
+	private T buildAbstractSchemaNameProposal(IEntity abstractSchemaType) {
+		String proposal = abstractSchemaType.getName();
+		return buildProposal(proposal, proposal, entityImage());
+	}
+
+	private Comparator<IEntity> buildEntityNameComparator() {
+		return new Comparator<IEntity>() {
+			public int compare(IEntity entity1, IEntity entity2) {
+				return entity1.getName().compareTo(entity2.getName());
+			}
+		};
+	}
+
+	private String buildIdentificationVariableDisplayString(String identificationVariable) {
+
+		IEntity abstractSchemaType = contentAssistProposals.getAbstractSchemaType(identificationVariable);
+
+		if (abstractSchemaType != null) {
+			StringBuilder sb = new StringBuilder();
+			sb.append(identificationVariable);
+			sb.append(" : ");
+			sb.append(abstractSchemaType.getName());
+			identificationVariable = sb.toString();
+		}
+
+		return identificationVariable;
+	}
+
+	private T buildIdentificationVariableProposal(String proposal) {
+		return buildProposal(
+			proposal,
+			buildIdentificationVariableDisplayString(proposal),
+			identificationVariableImage()
+		);
+	}
+
+	private T buildIdentifierProposal(String proposal) {
+
+		String additionalInfo = additionalInfo(proposal);
+		IdentifierRole role = JPQLExpression.identifierRole(proposal);
+		boolean realFunction = (role == IdentifierRole.FUNCTION) && isRealFunction(proposal);
+		int cursorOffset = 0;
+
+		// There is at least one letter before the cursor, if the setting "Match First Letter Case"
+		// is true, then match the case of the JPQL identifier with the first character
+		if ((partialWord.length() > 0) && shouldMatchFirstCharacterCase()) {
+			if (Character.isLowerCase(partialWord.charAt(0))) {
+				proposal = proposal.toLowerCase();
+			}
+		}
+		// Convert the case of the JPQL identifier based on the setting
+		else if (shouldUseLowercaseIdentifiers()) {
+			proposal = proposal.toLowerCase();
+		}
+
+		// For JPQL function, we add () to the display string, example: AVG()
+		// But for TRUE, FALSE, etc, we don't add ()
+		if (realFunction) {
+			proposal += "()";
+			cursorOffset--;
+		}
+
+		return buildProposal(
+			proposal,
+			proposal,
+			additionalInfo,
+			identifierImage(realFunction),
+			cursorOffset
+		);
+	}
+
+	private T buildMappingProposal(IMapping mapping) {
+		String proposal = mapping.getName();
+		return buildProposal(proposal, proposal, mappingImage(mapping));
+	}
+
+	private T buildProposal(String proposal, String displayString, Image image) {
+		return buildProposal(proposal, displayString, null, image, 0);
+	}
+
+	/**
+	 * Creates a new completion proposal for the given proposal.
+	 *
+	 * @param proposal A valid proposal that can be inserted into the query
+	 * @param displayString The human readable string of the proposal
+	 * @param additionalInfo Optional additional information about the proposal. The additional
+	 * information will be presented to assist the user in deciding if the selected proposal is the
+	 * desired choice
+	 * @param image The image that represents the proposal
+	 * @param cursorOffset An offset that moves the cursor backward or forward after it is adjusted
+	 * based on the given proposal
+	 * @return The completion proposal
+	 */
+	abstract T buildProposal(String proposal,
+	                         String displayString,
+	                         String additionalInfo,
+	                         Image image,
+	                         int cursorOffset);
+
+	/**
+	 * Creates the list of completion proposals based on the current content of the JPQL query and at
+	 * the specified position.
+	 *
+	 * @param namedQuery The model object used to access the application metadata information
+	 * @param actualQuery The model object may sometimes be out of sync with the actual content, the
+	 * actual query is required for proper content assist
+	 * @param offset The beginning of the string within the document
+	 * @param position The position of the cursor within the query, which starts at the beginning of
+	 * that query and not the document
+	 * @return The list of completion proposals
+	 */
+	final List<T> buildProposals(NamedQuery namedQuery, String actualQuery, int offset, int position) {
+
+		this.offset      = offset;
+		this.actualQuery = actualQuery;
+		this.namedQuery  = namedQuery;
+
+		// It's possible the string has literal representation of the escape characters, if required,
+		// convert them into actual escape characters and adjust the position accordingly
+		int[] positions  = { position };
+		this.jpqlQuery   = modifyJpqlQuery(actualQuery, positions);
+		this.position    = positions[0];
+		this.partialWord = partialWord();
+
+		// Gather the possible proposals
+		this.queryHelper.setQuery(namedQuery, jpqlQuery);
+		this.contentAssistProposals = queryHelper.buildContentAssistProposals(positions[0]);
+		this.queryHelper.dispose();
+
+		// Create the proposals for those proposals
+		List<T> proposals = new ArrayList<T>();
+		addAbstractSchemaNames    (proposals);
+		addIdentificationVariables(proposals);
+		addIdentifiers            (proposals);
+		addMappings               (proposals);
+
+		return proposals;
+	}
+
+	final void checkCanceled(IProgressMonitor monitor) throws InterruptedException {
+		if (monitor.isCanceled()) {
+			throw new InterruptedException();
+		}
+	}
+
+	/**
+	 * Clears the information used to retrieve the content assist proposals.
+	 */
+	final void clearInformation() {
+
+		offset      = -1;
+		position    = -1;
+		actualQuery = null;
+		namedQuery  = null;
+		partialWord = null;
+		contentAssistProposals = null;
+	}
+
+	private Image entityImage() {
+		return getImage(JptUiIcons.ENTITY);
+	}
+
+	/**
+	 * Returns the reason why this computer was unable to produce any completion proposals or
+	 * context information.
+	 *
+	 * @return An error message or <code>null</code> if no error occurred
+	 */
+	public String getErrorMessage() {
+		return null;
+	}
+
+	private Image getImage(String key) {
+		ImageRegistry imageRegistry = getImageRegistry();
+		Image image = imageRegistry.get(key);
+		if (image == null) {
+			imageRegistry.put(key, getImageDescriptor(key));
+			image = imageRegistry.get(key);
+		}
+		return image;
+	}
+
+	private ImageDescriptor getImageDescriptor(String key) {
+		return JptJpaUiPlugin.getImageDescriptor(key);
+	}
+
+	private ImageRegistry getImageRegistry() {
+		if (imageRegistry == null) {
+			imageRegistry = new ImageRegistry(Display.getCurrent());
+		}
+		return imageRegistry;
+	}
+
+	private Image identificationVariableImage() {
+		return getImage(JptUiIcons.JPQL_VARIABLE);
+	}
+
+	private Image identifierImage(boolean function) {
+
+		if (function) {
+			return getImage(JptUiIcons.JPQL_FUNCTION);
+		}
+
+		return getImage(JptUiIcons.JPQL_IDENTIFIER);
+	}
+
+	private boolean isRealFunction(String identifier) {
+		return identifier != Expression.TRUE         &&
+		       identifier != Expression.FALSE        &&
+		       identifier != Expression.NULL         &&
+		       identifier != Expression.CURRENT_DATE &&
+		       identifier != Expression.CURRENT_TIME &&
+		       identifier != Expression.CURRENT_TIMESTAMP;
+	}
+
+	private Image mappingImage(IMapping mapping) {
+		switch (mapping.getMappingType()) {
+			case BASIC:               return getImage(JptUiIcons.BASIC);
+			case BASIC_COLLECTION:    return getImage(JptUiIcons.ELEMENT_COLLECTION);
+			case BASIC_MAP:           return getImage(JptUiIcons.ELEMENT_COLLECTION);
+			case ELEMENT_COLLECTION:  return getImage(JptUiIcons.ELEMENT_COLLECTION);
+			case EMBEDDED:            return getImage(JptUiIcons.EMBEDDED);
+			case EMBEDDED_ID:         return getImage(JptUiIcons.EMBEDDED_ID);
+			case ID:                  return getImage(JptUiIcons.ID);
+			case MANY_TO_MANY:        return getImage(JptUiIcons.MANY_TO_MANY);
+			case MANY_TO_ONE:         return getImage(JptUiIcons.MANY_TO_ONE);
+			case ONE_TO_MANY:         return getImage(JptUiIcons.ONE_TO_MANY);
+			case ONE_TO_ONE:          return getImage(JptUiIcons.ONE_TO_ONE);
+			case TRANSFORMATION:      return getImage(JptUiIcons.BASIC);      // TODO
+			case VARIABLE_ONE_TO_ONE: return getImage(JptUiIcons.ONE_TO_ONE); // TODO
+			case VERSION:             return getImage(JptUiIcons.VERSION);
+			default:                  return getImage(JptUiIcons.TRANSIENT);
+		}
+	}
+
+	/**
+	 * In some context, the given JPQL query needs to be modified before it is parsed.
+	 *
+	 * @param jpqlQuery The JPQL query to keep unchanged or to modify before parsing it
+	 * @param position The position of the cursor within the JPQL query, which needs to be updated if
+	 * the query is modified
+	 * @return The given JPQL query or a modified version that will be parsed
+	 */
+	String modifyJpqlQuery(String jpqlQuery, int[] position) {
+		return jpqlQuery;
+	}
+
+	private String partialWord() {
+		WordParser wordParser = new WordParser(jpqlQuery);
+		wordParser.setPosition(position);
+		return wordParser.partialWord();
+	}
+
+	/**
+	 * Informs the computer that a content assist session has ended.
+	 */
+	public void sessionEnded() {
+
+		queryHelper.disposeProvider();
+		clearInformation();
+
+		if (imageRegistry != null) {
+			imageRegistry.dispose();
+		}
+	}
+
+	/**
+	 * Informs the computer that a content assist session has started.
+	 */
+	public void sessionStarted() {
+		// Nothing to do
+	}
+
+	private boolean shouldMatchFirstCharacterCase() {
+		return JptJpaUiPlugin.instance().getPreferenceStore().getBoolean(JptJpaUiPlugin.JPQL_IDENTIFIER_MATCH_FIRST_CHARACTER_CASE_PREF_KEY);
+	}
+
+	private boolean shouldUseLowercaseIdentifiers() {
+		String value = JptJpaUiPlugin.instance().getPreferenceStore().getString(JptJpaUiPlugin.JPQL_IDENTIFIER_CASE_PREF_KEY);
+		return JptJpaUiPlugin.JPQL_IDENTIFIER_LOWERCASE_PREF_VALUE.equals(value);
+	}
+
+	private Iterable<IEntity> sortByNames(Iterable<IEntity> abstractSchemaTypes) {
+		return CollectionTools.sort(abstractSchemaTypes, buildEntityNameComparator());
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlIdentifierMessages.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlIdentifierMessages.java
new file mode 100644
index 0000000..e3739de
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/JpqlIdentifierMessages.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.ui.internal.jpql;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.persistence.jpa.internal.jpql.parser.Expression;
+
+/**
+ * The localized messages describing the JPQL identifiers.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+@SuppressWarnings({"nls", "restriction"})
+final class JpqlIdentifierMessages extends NLS {
+
+	// JPA 1.0 identifiers
+	public static String ABS;
+	public static String ALL;
+	public static String ANY;
+	public static String ASC;
+	public static String AVG;
+	public static String BETWEEN;
+	public static String BOTH;
+	public static String CONCAT;
+	public static String COUNT;
+	public static String CURRENT_DATE;
+	public static String CURRENT_TIME;
+	public static String CURRENT_TIMESTAMP;
+	public static String DELETE_FROM;
+	public static String DESC;
+	public static String DISTINCT;
+	public static String ESCAPE;
+	public static String EXISTS;
+	public static String FROM;
+	public static String GROUP_BY;
+	public static String HAVING;
+	public static String IN;
+	public static String IS_EMPTY;
+	public static String IS_NULL;
+	public static String JOIN;
+	public static String JOIN_FETCH;
+	public static String LEADING;
+	public static String LENGTH;
+	public static String LIKE;
+	public static String LOCATE;
+	public static String LOWER;
+	public static String MAX;
+	public static String MEMBER;
+	public static String MIN;
+	public static String MOD;
+	public static String NEW;
+	public static String OBJECT;
+	public static String ORDER_BY;
+	public static String SELECT;
+	public static String SIZE;
+	public static String SOME;
+	public static String SQRT;
+	public static String SUBSTRING;
+	public static String SUM;
+	public static String TRAILING;
+	public static String TRIM;
+	public static String UPDATE;
+	public static String UPPER;
+	public static String WHERE;
+
+	// JPA 2.0 identifiers
+	public static String CASE;
+	public static String COALESCE;
+	public static String ENTRY;
+	public static String INDEX;
+	public static String KEY;
+	public static String NULLIF;
+	public static String TYPE;
+	public static String VALUE;
+
+	// EclipseLink identifiers
+	public static String FUNC;
+	public static String TREAT;
+
+	// Reserved JPQL identifiers
+	public static String BIT_LENGTH;
+	public static String CHAR_LENGTH;
+	public static String CHARACTER_LENGTH;
+	public static String CLASS;
+	public static String POSITION;
+	public static String UNKNOWN;
+
+	static {
+		NLS.initializeMessages("jpt_ui_jpql_identifiers", JpqlIdentifierMessages.class);
+	}
+
+	JpqlIdentifierMessages() {
+		super();
+		throw new UnsupportedOperationException();
+	}
+
+	private static Map<String, String> registeredIdentifers;
+
+	private static Map<String, String> buildRegisteredIdentifers() {
+
+		Map<String, String> identifiers = new HashMap<String, String>();
+
+		identifiers.put(Expression.IS_NOT_EMPTY,  Expression.IS_EMPTY);
+		identifiers.put(Expression.IS_NOT_NULL,   Expression.IS_NULL);
+		identifiers.put(Expression.MEMBER_OF,     Expression.MEMBER);
+		identifiers.put(Expression.NOT_IN,        Expression.IN);
+		identifiers.put(Expression.NOT_BETWEEN,   Expression.BETWEEN);
+		identifiers.put(Expression.NOT_MEMBER,    Expression.MEMBER);
+		identifiers.put(Expression.NOT_MEMBER_OF, Expression.MEMBER);
+
+		identifiers.put(Expression.INNER_JOIN,      Expression.JOIN);
+		identifiers.put(Expression.LEFT_JOIN,       Expression.JOIN);
+		identifiers.put(Expression.LEFT_OUTER_JOIN, Expression.JOIN);
+
+		identifiers.put(Expression.INNER_JOIN_FETCH,      Expression.JOIN_FETCH);
+		identifiers.put(Expression.LEFT_JOIN_FETCH,       Expression.JOIN_FETCH);
+		identifiers.put(Expression.LEFT_OUTER_JOIN_FETCH, Expression.JOIN_FETCH);
+
+		return identifiers;
+	}
+
+	/**
+	 * Converts the given JPQL identifier to the shortest form that is used to map the localized
+	 * message. If the identifier is <b>NOT MEMBER</b> for instance, then it needs to be converted
+	 * to <b>MEMBER</b> since that's the identifier used to map the localize message.
+	 *
+	 * @param identifier The JPQL identifier to convert, if needed
+	 * @return Either the given JPQL identifier or its counterpart that is used to map the localized
+	 * message
+	 */
+	private static String convertIdentifier(String identifier) {
+		identifier = registeredIdentifer(identifier);
+		identifier = identifier.replace(" ", "_");
+		return identifier;
+	}
+
+	/**
+	 * Retrieves the localized message for the given string value, if it's a JPQL identifier.
+	 *
+	 * @param identifier The JPQL identifier for which its localized description is needed
+	 * @return The localized message describing the given JPQL identifier or <code>null</code> if the
+	 * given choice is not an identifier
+	 */
+	static String localizedMessage(String identifier) {
+		try {
+			identifier = convertIdentifier(identifier);
+			Field constant = JpqlIdentifierMessages.class.getField(identifier);
+			return (String) constant.get(null);
+		}
+		catch (Exception e) {
+			// The choice is not a JPQL identifier
+			return null;
+		}
+	}
+
+	private static String registeredIdentifer(String identifier) {
+		String another = registeredIdentifers().get(identifier);
+		if (another != null) {
+			return another;
+		}
+		return identifier;
+	}
+
+	private static Map<String, String> registeredIdentifers() {
+		if (registeredIdentifers == null) {
+			registeredIdentifers = buildRegisteredIdentifers();
+		}
+		return registeredIdentifers;
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/TextTransferHandler.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/TextTransferHandler.java
new file mode 100644
index 0000000..febb9a1
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/jpql/TextTransferHandler.java
@@ -0,0 +1,228 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Oracle. All rights reserved.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
+ * which accompanies this distribution.
+ * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
+ * and the Eclipse Distribution License is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ *
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.ui.internal.jpql;
+
+import org.eclipse.jface.text.IUndoManager;
+import org.eclipse.jpt.common.utility.internal.StringTools;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StyledText;
+import org.eclipse.swt.dnd.Clipboard;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.TransferData;
+import org.eclipse.swt.events.MenuEvent;
+import org.eclipse.swt.events.MenuListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.ui.internal.WorkbenchMessages;
+
+/**
+ * This handler adds a context menu onto a {@link StyledText} which have the default actions dealing
+ * with text editing: Undo | Cut, Copy, Paste, Delete | Select All.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+@SuppressWarnings("restriction")
+public final class TextTransferHandler {
+
+	private MenuItem copyMenuItem;
+	private MenuItem cutMenuItem;
+	private MenuItem deleteMenuItem;
+	private MenuItem pasteMenuItem;
+	private Menu popup;
+	private MenuItem selectAllMenuItem;
+	private StyledText styledText;
+	private IUndoManager undoManager;
+	private MenuItem undoMenuItem;
+
+	private TextTransferHandler(StyledText styledText, IUndoManager undoManager) {
+		super();
+		this.styledText  = styledText;
+		this.undoManager = undoManager;
+	}
+
+	/**
+	 * Installs a context menu onto the given {@link StyledText} which have the default actions
+	 * dealing with text editing: Undo | Cut, Copy, Paste, Delete | Select All.
+	 *
+	 * @param styledText The widget for which a context menu will be added
+	 * @param undoManager The manager to undo keystrokes
+	 */
+	public static void installContextMenu(StyledText styledText, IUndoManager undoManager) {
+		TextTransferHandler handler = new TextTransferHandler(styledText, undoManager);
+		handler.installPopup();
+	}
+
+	private SelectionAdapter buildCopySelectionListener() {
+		return new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				styledText.copy();
+			}
+		};
+	}
+
+	private SelectionListener buildCutSelectionListener() {
+		return new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				styledText.cut();
+			}
+		};
+	}
+
+	private SelectionListener buildDeleteSelectionListener() {
+		return new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				Point selection = styledText.getSelection();
+				styledText.replaceTextRange(selection.x, selection.y - selection.x, StringTools.EMPTY_STRING);
+			}
+		};
+	}
+
+	private MenuListener buildMenuListener() {
+		return new MenuListener() {
+			public void menuHidden(MenuEvent e) {
+			}
+			public void menuShown(MenuEvent e) {
+				update();
+			}
+		};
+	}
+
+	private SelectionListener buildPasteSelectionListener() {
+		return new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				styledText.paste();
+			}
+		};
+	}
+
+	private SelectionListener buildSelectAllSelectionListener() {
+		return new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				styledText.selectAll();
+			}
+		};
+	}
+
+	private SelectionListener buildUndoSelectionListener() {
+		return new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				undoManager.undo();
+			}
+		};
+	}
+
+	private boolean canCopy() {
+		Point selection = styledText.getSelection();
+		return selection.x != selection.y;
+	}
+
+	private boolean canCut() {
+		Point selection = styledText.getSelection();
+		return selection.x != selection.y;
+	}
+
+	private boolean canDelete() {
+		Point selection = styledText.getSelection();
+		return selection.x != selection.y;
+	}
+
+	private boolean canPaste() {
+
+		Clipboard clipboard = new Clipboard(styledText.getDisplay());
+		boolean canPaste = false;
+
+		for (TransferData data : clipboard.getAvailableTypes()) {
+			if (TextTransfer.getInstance().isSupportedType(data)) {
+				canPaste = true;
+				break;
+			}
+		}
+
+		clipboard.dispose();
+		return canPaste;
+	}
+
+	private boolean canSelectAll() {
+		Point selection = styledText.getSelection();
+		String text = styledText.getText();
+		return (selection.y - selection.x) != text.length();
+	}
+
+	private void installPopup() {
+
+		popup = new Menu(styledText.getShell(), SWT.POP_UP);
+		popup.addMenuListener(buildMenuListener());
+		styledText.setMenu(popup);
+
+		populatePopup();
+	}
+
+	private void populatePopup() {
+
+		// Undo
+		undoMenuItem = new MenuItem(popup, SWT.PUSH);
+		undoMenuItem.setText(WorkbenchMessages.Workbench_undo);
+		undoMenuItem.addSelectionListener(buildUndoSelectionListener());
+
+		new MenuItem(popup, SWT.SEPARATOR);
+
+		// Cut
+		cutMenuItem = new MenuItem(popup, SWT.PUSH);
+		cutMenuItem.setText(WorkbenchMessages.Workbench_cut);
+		cutMenuItem.addSelectionListener(buildCutSelectionListener());
+
+		// Copy
+		copyMenuItem = new MenuItem(popup, SWT.PUSH);
+		copyMenuItem.setText(WorkbenchMessages.Workbench_copy);
+		copyMenuItem.addSelectionListener(buildCopySelectionListener());
+
+		// Paste
+		pasteMenuItem = new MenuItem(popup, SWT.PUSH);
+		pasteMenuItem.setText(WorkbenchMessages.Workbench_paste);
+		pasteMenuItem.addSelectionListener(buildPasteSelectionListener());
+
+		// Delete
+		deleteMenuItem = new MenuItem(popup, SWT.PUSH);
+		deleteMenuItem.setText(WorkbenchMessages.Workbench_delete);
+		deleteMenuItem.addSelectionListener(buildDeleteSelectionListener());
+
+		new MenuItem(popup, SWT.SEPARATOR);
+
+		// Select All
+		selectAllMenuItem = new MenuItem(popup, SWT.PUSH);
+		selectAllMenuItem.setText(WorkbenchMessages.Workbench_selectAll);
+		selectAllMenuItem.addSelectionListener(buildSelectAllSelectionListener());
+	}
+
+	private void update() {
+		deleteMenuItem   .setEnabled(canDelete());
+		copyMenuItem     .setEnabled(canCopy());
+		cutMenuItem      .setEnabled(canCut());
+		pasteMenuItem    .setEnabled(canPaste());
+		selectAllMenuItem.setEnabled(canSelectAll());
+		undoMenuItem     .setEnabled(undoManager.undoable());
+	}
+}
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/preferences/JpaPreferencesPage.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/preferences/JpaPreferencesPage.java
index 7432814..323950f 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/preferences/JpaPreferencesPage.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/preferences/JpaPreferencesPage.java
@@ -9,33 +9,45 @@
  ******************************************************************************/
 package org.eclipse.jpt.jpa.ui.internal.preferences;
 
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.jface.preference.PreferencePage;
 import org.eclipse.jpt.jpa.ui.JptJpaUiPlugin;
 import org.eclipse.jpt.jpa.ui.internal.JptUiMessages;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.ui.IWorkbench;
 import org.eclipse.ui.IWorkbenchPreferencePage;
 
 /**
- * This is the root of the Java Persistence preferences hierarchy in the IDE
- * preferences dialog.
+ * This is the root of the Java Persistence preferences hierarchy in the IDE preferences dialog.
  * <p>
  * Structure:
  * <p>
- * Java Persistence<br>
+ * JPA<br>
  *  |- Errors/Warnings
  *
- * @version 2.2
- * @since 2.2
+ * @version 3.0
+ * @since 3.0
  */
 public class JpaPreferencesPage extends PreferencePage
                                 implements IWorkbenchPreferencePage {
 
+	private boolean lowercase;
+	private Button lowerCaseRadioButton;
+	private boolean matchFirstCharacterCase;
+	private Button matchFirstCharacterCaseCheckBox;
+	private Button upperCaseRadioButton;
+
 	/**
 	 * Creates a new <code>JpaPreferencesPage</code>.
 	 */
@@ -43,19 +55,90 @@
 		super();
 	}
 
+	private void addJpqlEditorGroup(Composite parent) {
+
+		// JPQL Editing group box
+		Group group = new Group(parent, SWT.NONE);
+		group.setText(JptUiMessages.JpaPreferencesPage_jpqlEditor);
+		group.setLayout(new GridLayout());
+		group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+		// Top description
+		Label description = new Label(group, SWT.NONE);
+		description.setText(JptUiMessages.JpaPreferencesPage_jpqlEditor_description);
+
+		// Uppercase radio button
+		lowerCaseRadioButton = new Button(group, SWT.RADIO);
+		lowerCaseRadioButton.setText(JptUiMessages.JpaPreferencesPage_jpqlEditor_lowerCaseRadioButton);
+		lowerCaseRadioButton.addSelectionListener(buildLowercaseSelectionListener());
+		lowerCaseRadioButton.setSelection(lowercase);
+
+		// Uppercase radio button
+		upperCaseRadioButton = new Button(group, SWT.RADIO);
+		upperCaseRadioButton.setText(JptUiMessages.JpaPreferencesPage_jpqlEditor_upperCaseRadioButton);
+		upperCaseRadioButton.addSelectionListener(buildUppercaseSelectionListener());
+		upperCaseRadioButton.setSelection(!lowercase);
+
+		new Label(group, SWT.NONE);
+
+		// Match Case of First Letter check box
+		matchFirstCharacterCaseCheckBox = new Button(group, SWT.CHECK);
+		matchFirstCharacterCaseCheckBox.setText(JptUiMessages.JpaPreferencesPage_jpqlEditor_matchFirstCharacterCaseRadioButton);
+		matchFirstCharacterCaseCheckBox.addSelectionListener(buildMatchFirstCharacterCaseSelectionListener());
+		matchFirstCharacterCaseCheckBox.setSelection(matchFirstCharacterCase);
+	}
+
+	private SelectionListener buildLowercaseSelectionListener() {
+		return new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				Button button = (Button) e.widget;
+				lowercase = button.getSelection();
+			}
+		};
+	}
+
+	private SelectionListener buildMatchFirstCharacterCaseSelectionListener() {
+		return new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				Button button = (Button) e.widget;
+				matchFirstCharacterCase = button.getSelection();
+			}
+		};
+	}
+
+	private SelectionListener buildUppercaseSelectionListener() {
+		return new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				Button button = (Button) e.widget;
+				lowercase = !button.getSelection();
+			}
+		};
+	}
+
 	/**
 	 * {@inheritDoc}
 	 */
 	@Override
 	protected Control createContents(Composite parent) {
+		initializeDialogUnits(parent);
+
 		parent = new Composite(parent, SWT.NONE);
-		parent.setLayout(new GridLayout(1, false));
+		GridLayout layout = new GridLayout(1, false);
+		layout.marginWidth = 0;
+		layout.marginHeight = 0;
+		layout.verticalSpacing = convertVerticalDLUsToPixels(10);
+		layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+		parent.setLayout(layout);
 
-		// Message label
-		Label label = new Label(parent, SWT.NONE);
-		label.setText(JptUiMessages.JpaPreferencesPage_Description);
-		label.setData(new GridData(GridData.BEGINNING, GridData.BEGINNING, true, true));
+		Label description = new Label(parent, SWT.NONE);
+		description.setText(JptUiMessages.JpaPreferencesPage_description);
 
+		addJpqlEditorGroup(parent);
+
+		Dialog.applyDialogFont(parent);
 		return parent;
 	}
 
@@ -64,5 +147,55 @@
 	 */
 	public void init(IWorkbench workbench) {
 		setPreferenceStore(JptJpaUiPlugin.instance().getPreferenceStore());
+		lowercase = shouldUseLowercaseIdentifiers();
+		matchFirstCharacterCase = shouldMatchFirstCharacterCase();
+	}
+
+	private boolean isDefaultJpqlIdentifierLowercase() {
+		String value = getPreferenceStore().getDefaultString(JptJpaUiPlugin.JPQL_IDENTIFIER_CASE_PREF_KEY);
+		return JptJpaUiPlugin.JPQL_IDENTIFIER_LOWERCASE_PREF_VALUE.equals(value);
+	}
+
+	private String jpqlIdentifierPreferenceValue() {
+		return lowercase ? JptJpaUiPlugin.JPQL_IDENTIFIER_LOWERCASE_PREF_VALUE : JptJpaUiPlugin.JPQL_IDENTIFIER_UPPERCASE_PREF_VALUE;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	protected void performDefaults() {
+
+		lowercase = isDefaultJpqlIdentifierLowercase();
+		matchFirstCharacterCase = shouldDefaultMatchFirstCharacterCase();
+
+		lowerCaseRadioButton.setSelection(lowercase);
+		upperCaseRadioButton.setSelection(!lowercase);
+		matchFirstCharacterCaseCheckBox.setSelection(matchFirstCharacterCase);
+
+		super.performDefaults();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public boolean performOk() {
+		getPreferenceStore().setValue(JptJpaUiPlugin.JPQL_IDENTIFIER_CASE_PREF_KEY, jpqlIdentifierPreferenceValue());
+		getPreferenceStore().setValue(JptJpaUiPlugin.JPQL_IDENTIFIER_MATCH_FIRST_CHARACTER_CASE_PREF_KEY, matchFirstCharacterCase);
+		return super.performOk();
+	}
+
+	private boolean shouldDefaultMatchFirstCharacterCase() {
+		return getPreferenceStore().getDefaultBoolean(JptJpaUiPlugin.JPQL_IDENTIFIER_MATCH_FIRST_CHARACTER_CASE_PREF_KEY);
+	}
+
+	private boolean shouldMatchFirstCharacterCase() {
+		return getPreferenceStore().getBoolean(JptJpaUiPlugin.JPQL_IDENTIFIER_MATCH_FIRST_CHARACTER_CASE_PREF_KEY);
+	}
+
+	private boolean shouldUseLowercaseIdentifiers() {
+		String value = getPreferenceStore().getString(JptJpaUiPlugin.JPQL_IDENTIFIER_CASE_PREF_KEY);
+		return JptJpaUiPlugin.JPQL_IDENTIFIER_LOWERCASE_PREF_VALUE.equals(value);
 	}
 }
\ No newline at end of file
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/preferences/JpaProblemSeveritiesPage.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/preferences/JpaProblemSeveritiesPage.java
index 6dd7083..c0e5edb 100644
--- a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/preferences/JpaProblemSeveritiesPage.java
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/preferences/JpaProblemSeveritiesPage.java
@@ -73,13 +73,13 @@
 
 	/**
 	 * Default severity levels are stored here,  ERROR is the default default so only need
-	 * to include WARNING, INFO, IGNORE in this Map. These will be displayed if neither the project 
+	 * to include WARNING, INFO, IGNORE in this Map. These will be displayed if neither the project
 	 * or workspace preference applies.
 	 * <br> key is the preferenceKey which is also the validation message key @see JpaValidationMessages.
 	 * <br> value is a severity level - @see JpaValidationPreferences#ERROR WARNING INFO IGNORE
 	 */
 	private Map<String, String> defaultSeverities;
-	
+
 	/**
 	 * The list of <code>Combo</code>s is cached in order to perform a revert of
 	 * the properties.
@@ -335,7 +335,7 @@
 	private void addAttributeLevelCategory(Composite parent) {
 
 		parent = addExpandableSection(parent, JptUiValidationPreferenceMessages.ATTRIBUTE_LEVEL_CATEGORY);
-		
+
 		addLabeledCombo(
 			parent, JptUiValidationPreferenceMessages.PERSISTENT_ATTRIBUTE_UNSPECIFIED_NAME,
 			JpaValidationMessages.PERSISTENT_ATTRIBUTE_UNSPECIFIED_NAME);
@@ -395,7 +395,7 @@
 			JpaValidationMessages.ELEMENT_COLLECTION_MAP_KEY_CLASS_NOT_DEFINED);
 
 		parent = addSubExpandableSection(parent, JptUiValidationPreferenceMessages.IMPLIED_ATTRIBUTE_LEVEL_CATEGORY);
-		
+
 		addLabeledCombo(
 			parent, JptUiValidationPreferenceMessages.VIRTUAL_ATTRIBUTE_TARGET_ENTITY_IS_NOT_AN_ENTITY,
 			JpaValidationMessages.VIRTUAL_ATTRIBUTE_TARGET_ENTITY_IS_NOT_AN_ENTITY);
@@ -410,7 +410,7 @@
 			JpaValidationMessages.VIRTUAL_ATTRIBUTE_ELEMENT_COLLECTION_TARGET_CLASS_MUST_BE_EMBEDDABLE_OR_BASIC_TYPE);
 		addLabeledCombo(
 			parent, JptUiValidationPreferenceMessages.VIRTUAL_ATTRIBUTE_ELEMENT_COLLECTION_MAP_KEY_CLASS_NOT_DEFINED,
-			JpaValidationMessages.VIRTUAL_ATTRIBUTE_ELEMENT_COLLECTION_MAP_KEY_CLASS_NOT_DEFINED);	
+			JpaValidationMessages.VIRTUAL_ATTRIBUTE_ELEMENT_COLLECTION_MAP_KEY_CLASS_NOT_DEFINED);
 	}
 
 	private void addDatabaseCategory(Composite parent) {
@@ -423,9 +423,9 @@
 	}
 
 	private void addTableCategory(Composite parent) {
-		
+
 		parent = addExpandableSection(parent, JptUiValidationPreferenceMessages.TABLE_CATEGORY);
-		
+
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.TABLE_UNRESOLVED_CATALOG,                                            					JpaValidationMessages.TABLE_UNRESOLVED_CATALOG);
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.TABLE_UNRESOLVED_SCHEMA,                                             					JpaValidationMessages.TABLE_UNRESOLVED_SCHEMA);
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.TABLE_UNRESOLVED_NAME,                                               					JpaValidationMessages.TABLE_UNRESOLVED_NAME);
@@ -452,10 +452,10 @@
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.VIRTUAL_ATTRIBUTE_COLLECTION_TABLE_UNRESOLVED_SCHEMA,                                 JpaValidationMessages.VIRTUAL_ATTRIBUTE_COLLECTION_TABLE_UNRESOLVED_SCHEMA);
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.VIRTUAL_ATTRIBUTE_COLLECTION_TABLE_UNRESOLVED_NAME,                                   JpaValidationMessages.VIRTUAL_ATTRIBUTE_COLLECTION_TABLE_UNRESOLVED_NAME);
 	}
-	
-	private void addColumnCategory(Composite parent) {	
+
+	private void addColumnCategory(Composite parent) {
 		parent = addExpandableSection(parent, JptUiValidationPreferenceMessages.COLUMN_CATEGORY);
-		
+
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.COLUMN_TABLE_NOT_VALID,                                      							JpaValidationMessages.COLUMN_TABLE_NOT_VALID);
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.COLUMN_UNRESOLVED_TABLE,                                             					JpaValidationMessages.COLUMN_UNRESOLVED_TABLE);
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.COLUMN_UNRESOLVED_NAME,                                              					JpaValidationMessages.COLUMN_UNRESOLVED_NAME);
@@ -503,7 +503,7 @@
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.VIRTUAL_ATTRIBUTE_MAP_KEY_COLUMN_TABLE_NOT_VALID, 													JpaValidationMessages.VIRTUAL_ATTRIBUTE_MAP_KEY_COLUMN_TABLE_NOT_VALID);
 	}
 
-	private void addOverridesCategory(Composite parent) {	
+	private void addOverridesCategory(Composite parent) {
 
 		parent = addExpandableSection(parent, JptUiValidationPreferenceMessages.OVERRIDES_CATEGORY);
 
@@ -529,7 +529,7 @@
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.VIRTUAL_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_INVERSE_JOIN_COLUMNS, 				JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_INVERSE_JOIN_COLUMNS);
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.VIRTUAL_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_INVERSE_JOIN_COLUMNS, JpaValidationMessages.VIRTUAL_ASSOCIATION_OVERRIDE_INVERSE_JOIN_COLUMN_REFERENCED_COLUMN_NAME_MUST_BE_SPECIFIED_MULTIPLE_INVERSE_JOIN_COLUMNS);
 
-		
+
 		parent = addSubExpandableSection(parent, JptUiValidationPreferenceMessages.IMPLIED_ATTRIBUTE_LEVEL_CATEGORY);
 
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.VIRTUAL_ATTRIBUTE_ATTRIBUTE_OVERRIDE_INVALID_NAME,                  									JpaValidationMessages.VIRTUAL_ATTRIBUTE_ATTRIBUTE_OVERRIDE_INVALID_NAME);
@@ -591,12 +591,13 @@
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.ID_MAPPING_UNRESOLVED_GENERATOR_NAME, JpaValidationMessages.ID_MAPPING_UNRESOLVED_GENERATOR_NAME);
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.GENERATED_VALUE_UNRESOLVED_GENERATOR, JpaValidationMessages.GENERATED_VALUE_UNRESOLVED_GENERATOR);
 		addLabeledCombo(parent, JptUiValidationPreferenceMessages.QUERY_DUPLICATE_NAME,                 JpaValidationMessages.QUERY_DUPLICATE_NAME);
+		addLabeledCombo(parent, JptUiValidationPreferenceMessages.JPQL_QUERY_VALIDATION,                JpaValidationMessages.JPQL_QUERY_VALIDATION);
 	}
-	
+
 	private Composite addExpandableSection(Composite parent, String text) {
 		return addExpandableSection(parent, text, new GridData(GridData.FILL, GridData.FILL, true, false));
 	}
-	
+
 	private Composite addSubExpandableSection(Composite parent, String text) {
 		return addExpandableSection(parent, text, new GridData(GridData.FILL, GridData.FILL, true, false, 2, 1));
 	}
@@ -714,7 +715,7 @@
 		String preference = this.defaultSeverities.get(preferenceKey);
 		return preference == null ? JpaValidationPreferences.ERROR : preference;
 	}
-	
+
 	protected int convertPreferenceValueToComboIndex(String preferenceValue) {
 		if (JpaValidationPreferences.ERROR.equals(preferenceValue)) {
 			return ERROR_INDEX;
@@ -778,7 +779,7 @@
 			revertToDefault();
 		}
 	}
-	
+
 	@Override
 	protected void enableProjectSpecificSettings(boolean useProjectSpecificSettings) {
 		super.enableProjectSpecificSettings(useProjectSpecificSettings);
@@ -787,9 +788,9 @@
 			//      "otherwise the 'enable project specific settings' checkbox is being pressed")
 			return;
 		}
-		
+
 		this.hasProjectSpecificPreferences = Boolean.valueOf(useProjectSpecificSettings);
-		
+
 		//set all specified workspace preferences in the project preferences
 		if (useProjectSpecificSettings){
 			this.overrideWorkspacePreferences();
@@ -812,7 +813,7 @@
 				preference = getDefaultPreferenceValue(preferenceKey);
 			}
 			combo.select(convertPreferenceValueToComboIndex(preference));
-			//UI will show the defaults from the workspace, but set all preferences 
+			//UI will show the defaults from the workspace, but set all preferences
 			//to null so they will be deleted from project preferences
 			this.severityLevels.put(preferenceKey, null);
 		}
@@ -833,7 +834,7 @@
 			}
 		}
 	}
-	
+
 	// ********** OK/Revert/Apply behavior **********
 
 	@Override
@@ -858,7 +859,7 @@
 		}
 		catch (InterruptedException ex) {
 			return false;
-		} 
+		}
 		catch (InvocationTargetException ex) {
 			throw new RuntimeException(ex.getTargetException());
 		}
diff --git a/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/prefs/JpaUiPreferenceInitializer.java b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/prefs/JpaUiPreferenceInitializer.java
new file mode 100644
index 0000000..23cb2bf
--- /dev/null
+++ b/jpa/plugins/org.eclipse.jpt.jpa.ui/src/org/eclipse/jpt/jpa/ui/internal/prefs/JpaUiPreferenceInitializer.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 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.
+ *
+ * Contributors:
+ *     Oracle - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.jpt.jpa.ui.internal.prefs;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jpt.jpa.ui.JptJpaUiPlugin;
+
+/**
+ * The initializer of the JPA UI preferences, which sets the default values.
+ *
+ * @version 3.0
+ * @since 3.0
+ * @author Pascal Filion
+ */
+public class JpaUiPreferenceInitializer extends AbstractPreferenceInitializer {
+
+	/**
+	 * Creates a new <code>JpaUiPreferenceInitializer</code>.
+	 */
+	public JpaUiPreferenceInitializer() {
+		super();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public void initializeDefaultPreferences() {
+
+		IPreferenceStore preferences = JptJpaUiPlugin.instance().getPreferenceStore();
+		preferences.setDefault(JptJpaUiPlugin.JPQL_IDENTIFIER_CASE_PREF_KEY, JptJpaUiPlugin.JPQL_IDENTIFIER_LOWERCASE_PREF_VALUE);
+		preferences.setDefault(JptJpaUiPlugin.JPQL_IDENTIFIER_MATCH_FIRST_CHARACTER_CASE_PREF_KEY, true);
+	}
+}
\ No newline at end of file