Bug 550799 - Improve DataTemplate Editor reference handling

* Add a DataTemplate specific CreateNewModelElementStrategy which
forbids to add objects for non containment references
* Add a DataTemplate specific EObjectSelectionStrategy which only allows
objects from the same template
* Add RCPTT smoke test

Change-Id: I057c30f842d9a80fb1eed6b999312fd524d4c260
Signed-off-by: Eugen Neufeld <eneufeld@eclipsesource.com>
diff --git a/bundles/org.eclipse.emfforms.datatemplate.tooling/META-INF/MANIFEST.MF b/bundles/org.eclipse.emfforms.datatemplate.tooling/META-INF/MANIFEST.MF
index 443eb32..db5f121 100644
--- a/bundles/org.eclipse.emfforms.datatemplate.tooling/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.emfforms.datatemplate.tooling/META-INF/MANIFEST.MF
@@ -33,7 +33,10 @@
  org.eclipse.emf.databinding;bundle-version="[1.3.0,2.0.0)",
  org.eclipse.emfforms.swt.core.di;bundle-version="[1.22.0,1.23.0)"
 Bundle-RequiredExecutionEnvironment: JavaSE-1.8
-Service-Component: OSGI-INF/org.eclipse.emfforms.internal.datatemplate.tooling.editor.TemplateInstanceRendererService.xml,OSGI-INF/org.eclipse.emfforms.internal.datatemplate.tooling.editor.DataTemplateEClassSelectionStrategyProvider.xml
+Service-Component: OSGI-INF/org.eclipse.emfforms.internal.datatemplate.tooling.editor.TemplateInstanceRendererService.xml,
+ OSGI-INF/org.eclipse.emfforms.internal.datatemplate.tooling.editor.DataTemplateEClassSelectionStrategyProvider.xml,
+ OSGI-INF/org.eclipse.emfforms.internal.datatemplate.tooling.editor.DataTemplateEObjectSelectionStrategyProvider.xml,
+ OSGI-INF/org.eclipse.emfforms.internal.datatemplate.tooling.editor.DataTemplateCreateNewModelElementStrategyProvider.xml
 Bundle-ActivationPolicy: lazy
 Import-Package: javax.inject;version="1.0.0",
  org.eclipse.emf.ecp.ui.view.swt.reference;version="[1.22.0,1.23.0)",
diff --git a/bundles/org.eclipse.emfforms.datatemplate.tooling/src/org/eclipse/emfforms/internal/datatemplate/tooling/editor/DataTemplateCreateNewModelElementStrategyProvider.java b/bundles/org.eclipse.emfforms.datatemplate.tooling/src/org/eclipse/emfforms/internal/datatemplate/tooling/editor/DataTemplateCreateNewModelElementStrategyProvider.java
new file mode 100644
index 0000000..eb7d4cc
--- /dev/null
+++ b/bundles/org.eclipse.emfforms.datatemplate.tooling/src/org/eclipse/emfforms/internal/datatemplate/tooling/editor/DataTemplateCreateNewModelElementStrategyProvider.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2019 EclipseSource Muenchen GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Eugen Neufeld - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.emfforms.internal.datatemplate.tooling.editor;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecp.ui.view.swt.reference.CreateNewModelElementStrategy;
+import org.eclipse.emf.ecp.ui.view.swt.reference.CreateNewModelElementStrategy.Provider;
+import org.eclipse.emf.ecp.ui.view.swt.reference.ReferenceServiceCustomizationVendor;
+import org.eclipse.emfforms.bazaar.Create;
+import org.eclipse.emfforms.common.Optional;
+import org.eclipse.emfforms.datatemplate.Template;
+import org.eclipse.emfforms.datatemplate.TemplateCollection;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Display;
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * Provides a strategy to the DefaultReferenceService
+ * that does not allow to create objects in non containment references inside data templates.
+ *
+ * @author Eugen Neufeld
+ * @since 1.23
+ */
+@Component(property = "service.ranking:Integer=20")
+public class DataTemplateCreateNewModelElementStrategyProvider
+	extends ReferenceServiceCustomizationVendor<CreateNewModelElementStrategy> implements Provider {
+
+	@Override
+	protected boolean handles(EObject owner, EReference reference) {
+		return !(owner instanceof Template) && !reference.isContainment()
+			&& EcoreUtil.getRootContainer(owner) instanceof TemplateCollection;
+	}
+
+	/**
+	 * Creates the {@link CreateNewModelElementStrategy}.
+	 *
+	 * @return The created {@link CreateNewModelElementStrategy}
+	 */
+	@Create
+	public CreateNewModelElementStrategy createCreateNewModelElementStrategy() {
+		return new Strategy();
+	}
+
+	/**
+	 * The actual {@link CreateNewModelElementStrategy strategy} that informes the user, that a new object cannot be
+	 * created in a non containment references in a data template.
+	 *
+	 * @author Eugen Neufeld
+	 */
+	class Strategy implements CreateNewModelElementStrategy {
+
+		@Override
+		public Optional<EObject> createNewModelElement(EObject owner, EReference reference) {
+			MessageDialog.openInformation(Display.getDefault().getActiveShell(),
+				Messages.DataTemplateCreateNewModelElement_0,
+				Messages.DataTemplateCreateNewModelElement_1);
+			return Optional.empty();
+		}
+
+	}
+}
diff --git a/bundles/org.eclipse.emfforms.datatemplate.tooling/src/org/eclipse/emfforms/internal/datatemplate/tooling/editor/DataTemplateEObjectSelectionStrategyProvider.java b/bundles/org.eclipse.emfforms.datatemplate.tooling/src/org/eclipse/emfforms/internal/datatemplate/tooling/editor/DataTemplateEObjectSelectionStrategyProvider.java
new file mode 100644
index 0000000..2e3f2cd
--- /dev/null
+++ b/bundles/org.eclipse.emfforms.datatemplate.tooling/src/org/eclipse/emfforms/internal/datatemplate/tooling/editor/DataTemplateEObjectSelectionStrategyProvider.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2019 EclipseSource Muenchen GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Eugen Neufeld - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.emfforms.internal.datatemplate.tooling.editor;
+
+import java.util.Collection;
+import java.util.stream.Collectors;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecp.ui.view.swt.reference.EObjectSelectionStrategy;
+import org.eclipse.emf.ecp.ui.view.swt.reference.ReferenceServiceCustomizationVendor;
+import org.eclipse.emfforms.bazaar.Create;
+import org.eclipse.emfforms.datatemplate.Template;
+import org.eclipse.emfforms.datatemplate.TemplateCollection;
+import org.osgi.service.component.annotations.Component;
+
+/**
+ * Provider of an data template specific object selection strategy.
+ * The objects which are allowed to be selected must be from the same template as the object we want to add them to.
+ *
+ * @author Eugen Neufeld
+ * @since 1.23
+ */
+@Component(property = "service.ranking:Integer=5")
+public class DataTemplateEObjectSelectionStrategyProvider
+	extends ReferenceServiceCustomizationVendor<EObjectSelectionStrategy>
+	implements EObjectSelectionStrategy.Provider {
+
+	/**
+	 * Initializes me.
+	 */
+	public DataTemplateEObjectSelectionStrategyProvider() {
+		super();
+	}
+
+	@Override
+	protected boolean handles(EObject owner, EReference reference) {
+		return EcoreUtil.getRootContainer(owner) instanceof TemplateCollection;
+	}
+
+	/**
+	 * Create the selection strategy.
+	 *
+	 * @return the selection strategy
+	 */
+	@Create
+	public EObjectSelectionStrategy createEObjectSelectionStrategy() {
+		return new Strategy();
+	}
+
+	//
+	// Nested types
+	//
+
+	/**
+	 * The selection strategy.
+	 */
+	private static class Strategy implements EObjectSelectionStrategy {
+		/**
+		 * Initializes me.
+		 */
+		Strategy() {
+			super();
+		}
+
+		@Override
+		public Collection<EObject> collectExistingObjects(EObject owner, EReference reference,
+			Collection<EObject> existingObjects) {
+			final EObject template = getEnclosingTemplate(owner);
+			return existingObjects.stream().filter(o -> EcoreUtil.isAncestor(template,
+				o)).collect(Collectors.toList());
+		}
+
+		private EObject getEnclosingTemplate(EObject eObject) {
+			EObject parent = eObject.eContainer();
+			while (!(parent instanceof Template)) {
+				parent = parent.eContainer();
+			}
+			return parent;
+		}
+
+	}
+
+}
diff --git a/bundles/org.eclipse.emfforms.datatemplate.tooling/src/org/eclipse/emfforms/internal/datatemplate/tooling/editor/Messages.java b/bundles/org.eclipse.emfforms.datatemplate.tooling/src/org/eclipse/emfforms/internal/datatemplate/tooling/editor/Messages.java
new file mode 100644
index 0000000..ba43e24
--- /dev/null
+++ b/bundles/org.eclipse.emfforms.datatemplate.tooling/src/org/eclipse/emfforms/internal/datatemplate/tooling/editor/Messages.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2011-2019 EclipseSource Muenchen GmbH and others.
+ *
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * eugen - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.emfforms.internal.datatemplate.tooling.editor;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * @author Eugen Neufeld
+ * @generated
+ */
+public class Messages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.emfforms.internal.datatemplate.tooling.editor.messages"; //$NON-NLS-1$
+	public static String DataTemplateCreateNewModelElement_0;
+	public static String DataTemplateCreateNewModelElement_1;
+	static {
+		// initialize resource bundle
+		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+	}
+
+	private Messages() {
+	}
+}
diff --git a/bundles/org.eclipse.emfforms.datatemplate.tooling/src/org/eclipse/emfforms/internal/datatemplate/tooling/editor/messages.properties b/bundles/org.eclipse.emfforms.datatemplate.tooling/src/org/eclipse/emfforms/internal/datatemplate/tooling/editor/messages.properties
new file mode 100644
index 0000000..6e48c9b
--- /dev/null
+++ b/bundles/org.eclipse.emfforms.datatemplate.tooling/src/org/eclipse/emfforms/internal/datatemplate/tooling/editor/messages.properties
@@ -0,0 +1,2 @@
+DataTemplateCreateNewModelElement_0=Cannot create element
+DataTemplateCreateNewModelElement_1=Cannot add new objects to non-containment references in a template.
diff --git a/tests/ECPQ7Tests/EPPTests/update-site/project/DataTemplateEditor Smoke.test b/tests/ECPQ7Tests/EPPTests/update-site/project/DataTemplateEditor Smoke.test
new file mode 100644
index 0000000..f76ee19
--- /dev/null
+++ b/tests/ECPQ7Tests/EPPTests/update-site/project/DataTemplateEditor Smoke.test
@@ -0,0 +1,102 @@
+--- RCPTT testcase ---
+Format-Version: 1.0
+Contexts: _ihvnUC3mEeSwhO5Nwx0hPg,_ih4KMC3mEeSwhO5Nwx0hPg,_D4Pj4C3lEeSwhO5Nwx0hPg
+Element-Name: DataTemplateEditor Smoke
+Element-Type: testcase
+Element-Version: 3.0
+External-Reference: 
+Id: _XogaUM-8EemDG-PUFK2qgQ
+Runtime-Version: 2.4.2.201905052359
+Save-Time: 9/5/19 12:32 PM
+Testcase-Type: ecl
+
+------=_.content-0a7243a0-75d3-3d5f-9791-539de0e5b7ac
+Content-Type: text/ecl
+Entry-Name: .content
+
+get-view "Project Explorer" | get-tree | select "org.eclipse.emf.ecp.makeithappen.model.viewmodel" | get-menu 
+    -path "New/Other..." | click
+get-window New | get-button "Next >" | click
+with [get-window -class WizardDialog] {
+    get-editbox -after [get-label "File name:"] | set-text "test.datatemplate"
+    get-button Finish | click
+}
+with [get-editor "test.datatemplate"] {
+    get-tree | select "Template Collection" | get-menu -path Template | click
+    get-button "Create and link new Instance" | click
+}
+get-window "Select Sub Class and Template" | get-tree | select "template/ViewTemplate" | double-click
+with [get-editor "test.datatemplate"] {
+    get-tree | select "Template Collection/Template/View Template" | get-menu -path Style | click
+    get-button "Link Style Property" | click
+}
+get-window "Select Elements" | get-table | get-property itemCount | equals 0 | verify-true
+get-window "Select Elements" | get-button Cancel | click
+get-editor "test.datatemplate" | get-button "Create and link new Style Property" | click
+with [get-window "Select Sub Class and Template"] {
+    get-tree | select "fontProperties/FontPropertiesStyleProperty"
+    get-button Finish | click
+}
+get-window FontPropertiesStyleProperty | get-button OK | click
+with [get-editor "test.datatemplate"] {
+    get-tree | select "Template Collection/Template/View Template" | get-menu -path Style | click
+    get-button "Link Style Property" | click
+}
+get-window "Select Elements" | get-table | get-property itemCount | equals 1 | verify-true
+get-window "Select Elements" | get-button Cancel | click
+get-editor "test.datatemplate" | get-button "Create and link new Style Property" | click
+with [get-window "Select Sub Class and Template"] {
+    get-tree | select "tableValidation/TableValidationStyleProperty"
+    get-button Finish | click
+}
+with [get-window TableValidationStyleProperty] {
+    get-editbox -after [get-label "Column Width"] | set-focus
+    get-button Cancel | click
+}
+with [get-editor "test.datatemplate"] {
+    get-tree | select "Template Collection" | get-menu -path Template | click
+    get-button "Create and link new Instance" | click
+}
+with [get-window "Select Sub Class and Template"] {
+    get-tree | select "template/ViewTemplate"
+    get-button Finish | click
+}
+with [get-editor "test.datatemplate"] {
+    get-tree | select [get-item -path "Template Collection" | get-item -path Template -index 1 | get-item 
+        -path "View Template"] | get-menu -path Style | click
+    get-button "Link Style Property" | click
+}
+get-window "Select Elements" | get-table | get-property itemCount | equals 0 | verify-true
+get-window "Select Elements" | get-button Cancel | click
+with [get-editor "test.datatemplate"] {
+    get-tree | select "Template Collection" | get-menu -path Template | click
+    get-button "Create and link new Instance" | click
+}
+get-window "Select Sub Class and Template" | get-tree | select "bowling/League" | double-click
+with [get-editor "test.datatemplate"] {
+    get-tree | select [get-item -path "Template Collection" | get-item -path Template -index 2 | get-item -path League]
+    get-button "Add an instance of Player" | click
+    get-tree | select [get-item -path "Template Collection" | get-item -path Template -index 2]
+    get-button "Delete Reference" | click
+}
+get-window Confirmation | get-button Yes | click
+get-editor "test.datatemplate" | get-tree | get-item -path "Template Collection" | get-item -path Template -index 2 
+    | get-property childCount | equals 0 | verify-true
+with [get-editor "test.datatemplate"] {
+    get-tree | select [get-item -path "Template Collection" | get-item -path Template -index 2]
+    get-button "Create and link new Instance" | click
+}
+with [get-window "Select Sub Class and Template"] {
+    get-tree | select "bowling/Fan"
+    get-button Finish | click
+}
+with [get-editor "test.datatemplate"] {
+    get-tree | select [get-item -path "Template Collection" | get-item -path Template -index 2 | get-item -path Fan]
+    get-button "Create and link new Tournament" | click
+}
+get-window "Cannot create element" 
+    | get-label "This is a template, you cannot add new objects to non containment references here." 
+    | get-property caption 
+    | equals "This is a template, you cannot add new objects to non containment references here." | verify-true
+get-window "Cannot create element" | get-button OK | click
+------=_.content-0a7243a0-75d3-3d5f-9791-539de0e5b7ac--