Bug 553224 - [ViewModel] DMR resolution error messages
Add as much context about DMR resolution problems as is available to
the reference converter. Enhance existing JUnit tests to verify
details of exceptions; complete JUnit coverage of failure conditions.
Change-Id: I5fd2deb2422dd940d28a492e6037e13ac091378b
Signed-off-by: Christian W. Damus <give.a.damus@gmail.com>
diff --git a/bundles/org.eclipse.emfforms.core.services.databinding.featurepath/src/org/eclipse/emfforms/core/services/databinding/featurepath/FeaturePathDomainModelReferenceConverter.java b/bundles/org.eclipse.emfforms.core.services.databinding.featurepath/src/org/eclipse/emfforms/core/services/databinding/featurepath/FeaturePathDomainModelReferenceConverter.java
index 78d2d5d..39cb35f 100644
--- a/bundles/org.eclipse.emfforms.core.services.databinding.featurepath/src/org/eclipse/emfforms/core/services/databinding/featurepath/FeaturePathDomainModelReferenceConverter.java
+++ b/bundles/org.eclipse.emfforms.core.services.databinding.featurepath/src/org/eclipse/emfforms/core/services/databinding/featurepath/FeaturePathDomainModelReferenceConverter.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011-2016 EclipseSource Muenchen GmbH and others.
+ * 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
@@ -10,20 +10,26 @@
*
* Contributors:
* Lucas Koehler - initial API and implementation
+ * Christian W. Damus - bug 553224
******************************************************************************/
package org.eclipse.emfforms.core.services.databinding.featurepath;
import java.util.List;
+import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.databinding.IEMFListProperty;
import org.eclipse.emf.databinding.IEMFValueProperty;
import org.eclipse.emf.databinding.edit.EMFEditProperties;
import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.ENamedElement;
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecp.view.spi.model.VDomainModelReference;
import org.eclipse.emf.ecp.view.spi.model.VFeaturePathDomainModelReference;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
@@ -58,7 +64,8 @@
}
if (!VFeaturePathDomainModelReference.class.isInstance(domainModelReference)) {
throw new IllegalArgumentException(
- "DomainModelReference must be an instance of VFeaturePathDomainModelReference."); //$NON-NLS-1$
+ String.format("DomainModelReference %1$s is not an instance of VFeaturePathDomainModelReference.", //$NON-NLS-1$
+ identify(domainModelReference)));
}
final VFeaturePathDomainModelReference featurePathReference = (VFeaturePathDomainModelReference) domainModelReference;
@@ -68,7 +75,15 @@
}
if (featurePathReference.getDomainModelEFeature().eIsProxy()) {
throw new DatabindingFailedException(
- "The field domainModelEFeature of the given VFeaturePathDomainModelReference must not be a proxy."); //$NON-NLS-1$
+ String.format("The domainModelEFeature %1$s of the given DMR %2$s is a proxy.", //$NON-NLS-1$
+ identify(featurePathReference.getDomainModelEFeature()), identify(featurePathReference)));
+ }
+ for (final EReference path : featurePathReference.getDomainModelEReferencePath()) {
+ if (path.eIsProxy()) {
+ throw new DatabindingFailedException(
+ String.format("The path reference %1$s of the given DMR %2$s is a proxy.", //$NON-NLS-1$
+ identify(path), identify(featurePathReference)));
+ }
}
return featurePathReference;
}
@@ -93,16 +108,16 @@
if (referencePath.get(0).isMany()) {
throw new DatabindingFailedException(String.format(
- "The path is not fully resolved. The reference being resolved is not a single reference [%1$s]. The DMR is %2$s.", //$NON-NLS-1$
- referencePath.get(0), domainModelReference));
+ "The path is not fully resolved. The reference being resolved is not a single reference: %1$s. The DMR is %2$s.", //$NON-NLS-1$
+ identify(referencePath.get(0)), identify(domainModelReference)));
}
IEMFValueProperty emfValueProperty = EMFEditProperties.value(editingDomain, referencePath.get(0));
for (int i = 1; i < referencePath.size(); i++) {
final EReference eReference = referencePath.get(i);
if (eReference.isMany()) {
throw new DatabindingFailedException(String.format(
- "The path is not fully resolved. The reference being resolved is not a single reference [%1$s]. The DMR is %2$s.", //$NON-NLS-1$
- eReference, domainModelReference));
+ "The path is not fully resolved. The reference being resolved is not a single reference: %1$s. The DMR is %2$s.", //$NON-NLS-1$
+ identify(eReference), identify(domainModelReference)));
}
emfValueProperty = emfValueProperty.value(eReference);
}
@@ -140,32 +155,105 @@
for (final EReference eReference : featurePathReference.getDomainModelEReferencePath()) {
if (eReference.isMany()) {
throw new DatabindingFailedException(String.format(
- "The path is not fully resolved. The reference being resolved is not a single reference [%1$s]. The DMR is %2$s. Last resolved EObject is %3$s.", //$NON-NLS-1$
- eReference, domainModelReference, currentObject));
+ "The path is not fully resolved. The reference being resolved is not a single reference: %1$s. The DMR is %2$s. Last resolved EObject is %3$s.", //$NON-NLS-1$
+ identify(eReference), identify(domainModelReference), identify(currentObject)));
}
if (currentObject.eClass().getFeatureID(eReference) == -1) {
throw new DatabindingFailedException(String.format(
- "Given EClass has no such feature. The DMR is %1$s. Last resolved EObject is %2$s. Reference being resolved is %3$s.", //$NON-NLS-1$
- domainModelReference, currentObject, eReference));
+ "Given EClass %1$s has no such feature %2$s. The DMR is %3$s. Last resolved EObject is %4$s.", //$NON-NLS-1$
+ identify(currentObject.eClass()), identify(eReference),
+ identify(domainModelReference), identify(currentObject)));
}
final EObject nextObject = (EObject) currentObject.eGet(eReference);
if (nextObject == null) {
throw new DatabindingFailedException(String.format(
"The path is not fully resolved. The DMR is %1$s. Last resolved EObject is %2$s. Reference being resolved is %3$s.", //$NON-NLS-1$
- domainModelReference, currentObject, eReference));
+ identify(domainModelReference), identify(currentObject), identify(eReference)));
}
currentObject = nextObject;
}
final EStructuralFeature structuralFeature = featurePathReference.getDomainModelEFeature();
if (structuralFeature.getEType() == null) {
throw new DatabindingFailedException(
- String.format("The eType of the feature %1$s is null.", structuralFeature.getName())); //$NON-NLS-1$
+ String.format("The eType of the feature %1$s is null in DMR %2$s.", identify(structuralFeature), //$NON-NLS-1$
+ identify(domainModelReference)));
}
if (currentObject.eClass().getEAllStructuralFeatures().contains(structuralFeature)) {
return InternalEObject.class.cast(currentObject).eSetting(structuralFeature);
}
- throw new DatabindingFailedException(String.format("The resolved Object %1$s doesn't contain the feature %2$s.", //$NON-NLS-1$
- currentObject.eClass().getName(), structuralFeature.getName()));
+ throw new DatabindingFailedException(String.format("The resolved EObject %1$s doesn't have the feature %2$s.", //$NON-NLS-1$
+ identify(currentObject), identify(structuralFeature)));
+ }
+
+ private static String identify(EObject eObject) {
+ if (eObject == null) {
+ return "<null>"; //$NON-NLS-1$
+ }
+
+ final StringBuilder result = new StringBuilder();
+
+ // First, a trimmed variant of the to-string representation (omit Java package)
+ result.append(eObject.toString());
+ final int hashCodePos = result.indexOf("@"); //$NON-NLS-1$
+ if (hashCodePos > 0) {
+ final int lastDotPos = result.lastIndexOf(".", hashCodePos); //$NON-NLS-1$
+ if (lastDotPos > 0) {
+ result.delete(0, lastDotPos + 1);
+ }
+ }
+
+ final Resource resource = eObject.eResource();
+ if (resource != null) {
+ result.append('<');
+ result.append(EcoreUtil.getURI(eObject));
+ result.append('>');
+ }
+
+ return result.toString();
+ }
+
+ private static String identify(ENamedElement element) {
+ if (element == null) {
+ return "<null>"; //$NON-NLS-1$
+ }
+
+ final StringBuilder result = new StringBuilder();
+
+ if (element.eIsProxy()) {
+ // Infer as much as possible
+ final URI proxyURI = EcoreUtil.getURI(element);
+
+ // Get the qualified ENamedElement name
+ String fragment = proxyURI.fragment();
+ while (!fragment.isEmpty() && fragment.charAt(0) == '/') {
+ fragment = fragment.substring(1);
+ }
+ result.append(fragment.replace('/', '.'));
+
+ // Get the package namespace (or Ecore path)
+ result.append(" ("); //$NON-NLS-1$
+ result.append(proxyURI.trimFragment());
+ result.append(')');
+ } else {
+ result.append(element.getName());
+
+ for (EObject container = element.eContainer(); container instanceof ENamedElement; container = container
+ .eContainer()) {
+
+ final ENamedElement parent = (ENamedElement) container;
+
+ if (parent instanceof EPackage) {
+ result.append(" ("); //$NON-NLS-1$
+ result.append(((EPackage) container).getNsURI());
+ result.append(')');
+ } else {
+ result.insert(0, '.');
+ result.insert(0, parent.getName());
+ }
+ }
+ }
+
+ return result.toString();
}
}
diff --git a/tests/org.eclipse.emfforms.core.services.databinding.featurepath.tests/All Integration Tests for core.services.databinding.featurepath.launch b/tests/org.eclipse.emfforms.core.services.databinding.featurepath.tests/All Integration Tests for core.services.databinding.featurepath.launch
index 3cc1a39..a1d816c 100644
--- a/tests/org.eclipse.emfforms.core.services.databinding.featurepath.tests/All Integration Tests for core.services.databinding.featurepath.launch
+++ b/tests/org.eclipse.emfforms.core.services.databinding.featurepath.tests/All Integration Tests for core.services.databinding.featurepath.launch
@@ -1,43 +1,44 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.pde.ui.JunitLaunchConfig">
-<booleanAttribute key="append.args" value="true"/>
-<stringAttribute key="application" value="org.eclipse.pde.junit.runtime.coretestapplication"/>
-<booleanAttribute key="askclear" value="false"/>
-<booleanAttribute key="automaticAdd" value="false"/>
-<booleanAttribute key="automaticValidate" value="false"/>
-<stringAttribute key="bootstrap" value=""/>
-<stringAttribute key="checked" value="[NONE]"/>
-<booleanAttribute key="clearConfig" value="true"/>
-<booleanAttribute key="clearws" value="true"/>
-<booleanAttribute key="clearwslog" value="false"/>
-<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/pde-junit"/>
-<booleanAttribute key="default" value="false"/>
-<booleanAttribute key="includeOptional" value="false"/>
-<stringAttribute key="location" value="${workspace_loc}/../junit-workspace"/>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-<listEntry value="/org.eclipse.emfforms.core.services.databinding.featurepath.tests/src/org/eclipse/emfforms/core/services/databinding/featurepath/tests/AllIntegrationTests.java"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-<listEntry value="1"/>
-</listAttribute>
-<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
-<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
-<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
-<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
-<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
-<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.emfforms.core.services.databinding.featurepath.tests.AllIntegrationTests"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.emfforms.core.services.databinding.featurepath.tests"/>
-<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
-<stringAttribute key="pde.version" value="3.3"/>
-<stringAttribute key="product" value="org.eclipse.emf.cdo.server.product.tcp_h2"/>
-<booleanAttribute key="run_in_ui_thread" value="true"/>
-<stringAttribute key="selected_target_plugins" value="com.ibm.icu@default:default,javax.xml@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.core.databinding.observable@default:default,org.eclipse.core.databinding.property@default:default,org.eclipse.core.databinding@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.runtime@default:true,org.eclipse.emf.common@default:default,org.eclipse.emf.databinding@default:default,org.eclipse.emf.ecore@default:default,org.eclipse.equinox.app@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.ds@1:true,org.eclipse.equinox.preferences@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.equinox.util@default:default,org.eclipse.osgi.services@default:default,org.eclipse.osgi@-1:true,org.hamcrest.core@default:default,org.junit@default:default,org.mockito.mockito-all@default:default"/>
-<stringAttribute key="selected_workspace_plugins" value="org.eclipse.emf.ecp.view.model@default:default,org.eclipse.emfforms.common@default:default,org.eclipse.emfforms.core.services.databinding.featurepath.tests@default:false,org.eclipse.emfforms.core.services.databinding.featurepath@default:default,org.eclipse.emfforms.core.services.databinding.testmodel@default:default,org.eclipse.emfforms.core.services.databinding@default:default"/>
-<booleanAttribute key="show_selected_only" value="false"/>
-<booleanAttribute key="tracing" value="false"/>
-<booleanAttribute key="useCustomFeatures" value="false"/>
-<booleanAttribute key="useDefaultConfig" value="true"/>
-<booleanAttribute key="useDefaultConfigArea" value="false"/>
-<booleanAttribute key="useProduct" value="false"/>
-</launchConfiguration>
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.pde.ui.JunitLaunchConfig">
+<booleanAttribute key="append.args" value="true"/>
+<stringAttribute key="application" value="org.eclipse.pde.junit.runtime.coretestapplication"/>
+<booleanAttribute key="askclear" value="false"/>
+<booleanAttribute key="automaticAdd" value="false"/>
+<booleanAttribute key="automaticValidate" value="false"/>
+<stringAttribute key="bootstrap" value=""/>
+<stringAttribute key="checked" value="[NONE]"/>
+<booleanAttribute key="clearConfig" value="true"/>
+<booleanAttribute key="clearws" value="true"/>
+<booleanAttribute key="clearwslog" value="false"/>
+<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/pde-junit"/>
+<booleanAttribute key="default" value="false"/>
+<booleanAttribute key="includeOptional" value="false"/>
+<stringAttribute key="location" value="${workspace_loc}/../junit-workspace"/>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/org.eclipse.emfforms.core.services.databinding.featurepath.tests/src/org/eclipse/emfforms/core/services/databinding/featurepath/tests/AllIntegrationTests.java"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="1"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value=""/>
+<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/>
+<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/>
+<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit4"/>
+<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/>
+<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="org.eclipse.emfforms.core.services.databinding.featurepath.tests.AllIntegrationTests"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.emfforms.core.services.databinding.featurepath.tests"/>
+<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
+<stringAttribute key="pde.version" value="3.3"/>
+<stringAttribute key="product" value="org.eclipse.emf.cdo.server.product.tcp_h2"/>
+<booleanAttribute key="run_in_ui_thread" value="true"/>
+<stringAttribute key="selected_target_plugins" value="com.ibm.icu@default:default,javax.inject@default:default,org.apache.felix.scr@1:true,org.eclipse.core.contenttype@default:default,org.eclipse.core.databinding.observable@default:default,org.eclipse.core.databinding.property@default:default,org.eclipse.core.databinding@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.runtime@default:true,org.eclipse.e4.core.contexts@default:default,org.eclipse.e4.core.di.annotations@default:default,org.eclipse.e4.core.di.extensions.supplier@default:default,org.eclipse.e4.core.di.extensions@default:default,org.eclipse.e4.core.di@default:default,org.eclipse.emf.common@default:default,org.eclipse.emf.databinding.edit@default:default,org.eclipse.emf.databinding@default:default,org.eclipse.emf.ecore.xmi@default:default,org.eclipse.emf.ecore@default:default,org.eclipse.emf.edit@default:default,org.eclipse.equinox.app@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.ds@1:true,org.eclipse.equinox.preferences@default:default,org.eclipse.equinox.registry@default:default,org.eclipse.equinox.util@default:default,org.eclipse.osgi.services@default:default,org.eclipse.osgi.util@default:default,org.eclipse.osgi@-1:true,org.hamcrest.core@default:default,org.junit@default:default,org.mockito.mockito-core-hamcrest-modified@default:default,org.objenesis@default:default"/>
+<stringAttribute key="selected_workspace_plugins" value="org.eclipse.emf.ecp.common@default:default,org.eclipse.emf.ecp.view.context@default:default,org.eclipse.emf.ecp.view.model.common@default:default,org.eclipse.emf.ecp.view.model@default:default,org.eclipse.emf.ecp.view.template.model@default:default,org.eclipse.emfforms.common@default:default,org.eclipse.emfforms.core.bazaar@default:default,org.eclipse.emfforms.core.services.databinding.featurepath.tests@default:false,org.eclipse.emfforms.core.services.databinding.featurepath@default:default,org.eclipse.emfforms.core.services.databinding.testmodel@default:default,org.eclipse.emfforms.core.services.emf@default:default,org.eclipse.emfforms.core.services.emfspecificservice@default:default,org.eclipse.emfforms.core.services@default:default,org.eclipse.emfforms.localization@default:default"/>
+<booleanAttribute key="show_selected_only" value="false"/>
+<booleanAttribute key="tracing" value="false"/>
+<booleanAttribute key="useCustomFeatures" value="false"/>
+<booleanAttribute key="useDefaultConfig" value="true"/>
+<booleanAttribute key="useDefaultConfigArea" value="false"/>
+<booleanAttribute key="useProduct" value="false"/>
+</launchConfiguration>
diff --git a/tests/org.eclipse.emfforms.core.services.databinding.featurepath.tests/src/org/eclipse/emfforms/internal/core/services/databinding/featurepath/FeaturePathDomainModelReferenceConverter_Test.java b/tests/org.eclipse.emfforms.core.services.databinding.featurepath.tests/src/org/eclipse/emfforms/internal/core/services/databinding/featurepath/FeaturePathDomainModelReferenceConverter_Test.java
index c824223..68c1fe4 100644
--- a/tests/org.eclipse.emfforms.core.services.databinding.featurepath.tests/src/org/eclipse/emfforms/internal/core/services/databinding/featurepath/FeaturePathDomainModelReferenceConverter_Test.java
+++ b/tests/org.eclipse.emfforms.core.services.databinding.featurepath.tests/src/org/eclipse/emfforms/internal/core/services/databinding/featurepath/FeaturePathDomainModelReferenceConverter_Test.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011-2018 EclipseSource Muenchen GmbH and others.
+ * 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
@@ -10,6 +10,7 @@
*
* Contributors:
* Lucas Koehler - initial API and implementation
+ * Christian W. Damus - bug 553224
******************************************************************************/
package org.eclipse.emfforms.internal.core.services.databinding.featurepath;
@@ -18,6 +19,7 @@
import static org.mockito.Mockito.mock;
import java.util.LinkedList;
+import java.util.regex.Pattern;
import org.eclipse.core.databinding.property.list.IListProperty;
import org.eclipse.core.databinding.property.value.IValueProperty;
@@ -27,6 +29,7 @@
import org.eclipse.emf.databinding.IEMFValueProperty;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
@@ -35,8 +38,13 @@
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
+import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
+import org.eclipse.emf.ecp.view.spi.model.VControl;
import org.eclipse.emf.ecp.view.spi.model.VDomainModelReference;
import org.eclipse.emf.ecp.view.spi.model.VFeaturePathDomainModelReference;
+import org.eclipse.emf.ecp.view.spi.model.VView;
import org.eclipse.emf.ecp.view.spi.model.VViewFactory;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
@@ -50,9 +58,13 @@
import org.eclipse.emfforms.core.services.databinding.testmodel.test.model.TestPackage;
import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedException;
import org.eclipse.emfforms.spi.core.services.databinding.DomainModelReferenceConverter;
+import org.hamcrest.CustomTypeSafeMatcher;
+import org.hamcrest.Matcher;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Rule;
import org.junit.Test;
+import org.junit.rules.ExpectedException;
/**
* JUnit test for {@link FeaturePathDomainModelReferenceConverter}.
@@ -65,6 +77,9 @@
private FeaturePathDomainModelReferenceConverter converter;
private static EObject validEObject;
+ @Rule
+ public final ExpectedException thrown = ExpectedException.none();
+
@BeforeClass
public static void setupClass() {
validEObject = createValidEObject();
@@ -81,11 +96,12 @@
private static Resource createVirtualResource() {
final ResourceSet rs = new ResourceSetImpl();
+ rs.getResourceFactoryRegistry().getExtensionToFactoryMap().put("xmi", new XMIResourceFactoryImpl()); //$NON-NLS-1$
final AdapterFactoryEditingDomain domain = new AdapterFactoryEditingDomain(
new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE),
new BasicCommandStack(), rs);
rs.eAdapters().add(new AdapterFactoryEditingDomain.EditingDomainProvider(domain));
- final Resource resource = rs.createResource(URI.createURI("VIRTAUAL_URI")); //$NON-NLS-1$
+ final Resource resource = rs.createResource(URI.createURI("VIRTUAL_URI.xmi")); //$NON-NLS-1$
return resource;
}
@@ -102,6 +118,28 @@
return AdapterFactoryEditingDomain.getEditingDomainFor(object);
}
+ private static VFeaturePathDomainModelReference createValidDMR() {
+ final Resource resource = createVirtualResource();
+ final VView view = VViewFactory.eINSTANCE.createView();
+ final VControl control = VViewFactory.eINSTANCE.createControl();
+ view.getChildren().add(control);
+ resource.getContents().add(view);
+ final VFeaturePathDomainModelReference result = VViewFactory.eINSTANCE.createFeaturePathDomainModelReference();
+ control.setDomainModelReference(result);
+ ((XMLResource) resource).setID(result, "theDMR"); //$NON-NLS-1$
+ return result;
+ }
+
+ static Matcher<String> find(String regex) {
+ return new CustomTypeSafeMatcher<String>("matches '" + regex + "'") { //$NON-NLS-1$//$NON-NLS-2$
+ @Override
+ protected boolean matchesSafely(String item) {
+ final java.util.regex.Matcher m = Pattern.compile(regex).matcher(item);
+ return m.find();
+ }
+ };
+ }
+
/**
* Set up that is executed before every test.
*/
@@ -133,8 +171,11 @@
* {@link org.eclipse.emfforms.core.services.databinding.featurepath.FeaturePathDomainModelReferenceConverter#isApplicable(org.eclipse.emf.ecp.view.spi.model.VDomainModelReference)}
* .
*/
- @Test(expected = IllegalArgumentException.class)
+ @Test
public void testIsApplicableNull() {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("must not be null"); //$NON-NLS-1$
+
converter.isApplicable(null);
}
@@ -212,8 +253,12 @@
*
* @throws DatabindingFailedException if the databinding failed
*/
- @Test(expected = DatabindingFailedException.class)
+ @Test
public void testConvertToValuePropertyNoFeature() throws DatabindingFailedException {
+ thrown.expect(DatabindingFailedException.class);
+ thrown.expectMessage("field domainModelEFeature"); //$NON-NLS-1$
+ thrown.expectMessage("must not be null"); //$NON-NLS-1$
+
final VFeaturePathDomainModelReference pathReference = VViewFactory.eINSTANCE
.createFeaturePathDomainModelReference();
converter.convertToValueProperty(pathReference, validEObject);
@@ -226,8 +271,11 @@
*
* @throws DatabindingFailedException if the databinding failed
*/
- @Test(expected = IllegalArgumentException.class)
+ @Test
public void testConvertToValuePropertyNull() throws DatabindingFailedException {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("must not be null"); //$NON-NLS-1$
+
converter.convertToValueProperty(null, validEObject);
}
@@ -238,9 +286,55 @@
*
* @throws DatabindingFailedException if the databinding failed
*/
- @Test(expected = IllegalArgumentException.class)
+ @Test
public void testConvertToValuePropertyWrongReferenceType() throws DatabindingFailedException {
- converter.convertToValueProperty(mock(VDomainModelReference.class), validEObject);
+ final VDomainModelReference dmr = mock(VDomainModelReference.class);
+
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("DomainModelReference " + dmr.toString()); //$NON-NLS-1$
+ thrown.expectMessage("is not an instance of VFeaturePathDomainModelReference"); //$NON-NLS-1$
+
+ converter.convertToValueProperty(dmr, validEObject);
+ }
+
+ @Test
+ public void testConvertToValuePropertyListReferenceFirstInPath() throws DatabindingFailedException {
+ thrown.expect(DatabindingFailedException.class);
+ thrown.expectMessage("not a single reference: A.bList (test)"); //$NON-NLS-1$
+ thrown.expectMessage("DMR is VFeaturePathDomainModelReferenceImpl@"); //$NON-NLS-1$
+
+ final VFeaturePathDomainModelReference pathReference = VViewFactory.eINSTANCE
+ .createFeaturePathDomainModelReference();
+ // create reference path to the attribute
+ final LinkedList<EReference> referencePath = new LinkedList<EReference>();
+ referencePath.add(TestPackage.Literals.A__BLIST);
+ referencePath.add(TestPackage.Literals.B__C);
+ referencePath.add(TestPackage.Literals.C__D);
+
+ pathReference.getDomainModelEReferencePath().addAll(referencePath);
+ pathReference.setDomainModelEFeature(TestPackage.Literals.D__X);
+
+ converter.convertToValueProperty(pathReference, validEObject);
+ }
+
+ @Test
+ public void testConvertToValuePropertyListReferenceInPath() throws DatabindingFailedException {
+ thrown.expect(DatabindingFailedException.class);
+ thrown.expectMessage("not a single reference: B.cList (test)"); //$NON-NLS-1$
+ thrown.expectMessage("DMR is VFeaturePathDomainModelReferenceImpl@"); //$NON-NLS-1$
+
+ final VFeaturePathDomainModelReference pathReference = VViewFactory.eINSTANCE
+ .createFeaturePathDomainModelReference();
+ // create reference path to the attribute
+ final LinkedList<EReference> referencePath = new LinkedList<EReference>();
+ referencePath.add(TestPackage.Literals.A__B);
+ referencePath.add(TestPackage.Literals.B__CLIST);
+ referencePath.add(TestPackage.Literals.C__D);
+
+ pathReference.getDomainModelEReferencePath().addAll(referencePath);
+ pathReference.setDomainModelEFeature(TestPackage.Literals.D__X);
+
+ converter.convertToValueProperty(pathReference, validEObject);
}
@Test
@@ -344,8 +438,12 @@
*
* @throws DatabindingFailedException if the databinding failed
*/
- @Test(expected = DatabindingFailedException.class)
+ @Test
public void testConvertToListPropertyNoFeature() throws DatabindingFailedException {
+ thrown.expect(DatabindingFailedException.class);
+ thrown.expectMessage("field domainModelEFeature"); //$NON-NLS-1$
+ thrown.expectMessage("must not be null"); //$NON-NLS-1$
+
final VFeaturePathDomainModelReference pathReference = VViewFactory.eINSTANCE
.createFeaturePathDomainModelReference();
converter.convertToListProperty(pathReference, validEObject);
@@ -388,8 +486,11 @@
*
* @throws DatabindingFailedException if the databinding failed
*/
- @Test(expected = IllegalArgumentException.class)
+ @Test
public void testConvertToListPropertyNull() throws DatabindingFailedException {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("must not be null"); //$NON-NLS-1$
+
converter.convertToListProperty(null, validEObject);
}
@@ -400,8 +501,11 @@
*
* @throws DatabindingFailedException if the databinding failed
*/
- @Test(expected = IllegalArgumentException.class)
+ @Test
public void testConvertToListPropertyWrongReferenceType() throws DatabindingFailedException {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("not an instance of VFeaturePathDomainModelReference"); //$NON-NLS-1$
+
converter.convertToListProperty(mock(VDomainModelReference.class), validEObject);
}
@@ -456,30 +560,203 @@
assertEquals(expected, setting.get(true));
}
- @Test(expected = DatabindingFailedException.class)
+ @Test
public void testGetSettingNoFeature() throws DatabindingFailedException {
+ thrown.expect(DatabindingFailedException.class);
+ thrown.expectMessage("field domainModelEFeature"); //$NON-NLS-1$
+ thrown.expectMessage("must not be null"); //$NON-NLS-1$
+
final VFeaturePathDomainModelReference pathReference = VViewFactory.eINSTANCE
.createFeaturePathDomainModelReference();
converter.getSetting(pathReference, validEObject);
}
- @Test(expected = IllegalArgumentException.class)
+ @Test
public void testGetSettingNull() throws DatabindingFailedException {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("must not be null"); //$NON-NLS-1$
+
converter.getSetting(null, validEObject);
}
- @Test(expected = IllegalArgumentException.class)
+ @Test
public void testGetSettingWrongReferenceType() throws DatabindingFailedException {
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("not an instance of VFeaturePathDomainModelReference"); //$NON-NLS-1$
+
converter.getSetting(mock(VDomainModelReference.class), validEObject);
}
- @Test(expected = DatabindingFailedException.class)
+ @Test
public void testGetSettingInvalidFeatureInPath() throws DatabindingFailedException {
- final VFeaturePathDomainModelReference reference = VViewFactory.eINSTANCE
- .createFeaturePathDomainModelReference();
- reference.getDomainModelEReferencePath().add(TestPackage.eINSTANCE.getDExtended_A());
- reference.setDomainModelEFeature(TestPackage.eINSTANCE.getA_B());
- final D d = TestFactory.eINSTANCE.createD();
+ thrown.expect(DatabindingFailedException.class);
+ thrown.expectMessage("EClass D (test) has no such feature DExtended.a (test)"); //$NON-NLS-1$
+ thrown.expectMessage(find(
+ "The DMR is VFeaturePathDomainModelReferenceImpl@\\p{XDigit}+ \\(changeListener: null\\)<VIRTUAL_URI\\.xmi#theDMR>")); //$NON-NLS-1$
+ thrown.expectMessage(
+ find("resolved EObject is DImpl@\\p{XDigit}+ \\(x: null, yList: null\\)<VIRTUAL_URI\\.xmi#/>")); //$NON-NLS-1$
+
+ final D d = (D) createValidEObject(TestPackage.Literals.D);
+ final VFeaturePathDomainModelReference reference = createValidDMR();
+ reference.getDomainModelEReferencePath().add(TestPackage.Literals.DEXTENDED__A);
+ reference.setDomainModelEFeature(TestPackage.Literals.A__B);
converter.getSetting(reference, d);
}
+
+ @Test
+ public void testGetSettingUnresolvedFeature() throws DatabindingFailedException {
+ final EPackage pkg = EcoreFactory.eINSTANCE.createEPackage();
+ pkg.setName("gone"); //$NON-NLS-1$
+ pkg.setNsPrefix("gone"); //$NON-NLS-1$
+ pkg.setNsURI("http://www.eclipse.org/ecp/test/gone"); //$NON-NLS-1$
+ final EClass eClass = EcoreFactory.eINSTANCE.createEClass();
+ eClass.setName("Gone"); //$NON-NLS-1$
+ final EReference ref = EcoreFactory.eINSTANCE.createEReference();
+ ref.setName("ref"); //$NON-NLS-1$
+ ref.setEType(eClass);
+ eClass.getEStructuralFeatures().add(ref);
+ pkg.getEClassifiers().add(eClass);
+ final Resource resource = new EcoreResourceFactoryImpl().createResource(URI.createURI(pkg.getNsURI()));
+ resource.getContents().add(pkg);
+
+ thrown.expect(DatabindingFailedException.class);
+ thrown.expectMessage("domainModelEFeature Gone.ref (http://www.eclipse.org/ecp/test/gone)"); //$NON-NLS-1$
+ thrown.expectMessage(find(
+ "DMR VFeaturePathDomainModelReferenceImpl@\\p{XDigit}+ \\(changeListener: null\\)<VIRTUAL_URI\\.xmi#theDMR>")); //$NON-NLS-1$
+ thrown.expectMessage("is a proxy"); //$NON-NLS-1$
+
+ final D d = (D) createValidEObject(TestPackage.Literals.D);
+ final VFeaturePathDomainModelReference reference = createValidDMR();
+ reference.getDomainModelEReferencePath().add(TestPackage.Literals.DEXTENDED__A);
+ reference.setDomainModelEFeature(ref);
+
+ // Unload the package to proxify everything
+ resource.unload();
+
+ converter.getSetting(reference, d);
+ }
+
+ @Test
+ public void testGetSettingUnresolvedReferenceInPath() throws DatabindingFailedException {
+ final EPackage pkg = EcoreFactory.eINSTANCE.createEPackage();
+ pkg.setName("gone"); //$NON-NLS-1$
+ pkg.setNsPrefix("gone"); //$NON-NLS-1$
+ pkg.setNsURI("http://www.eclipse.org/ecp/test/gone"); //$NON-NLS-1$
+ final EClass eClass = EcoreFactory.eINSTANCE.createEClass();
+ eClass.setName("Gone"); //$NON-NLS-1$
+ final EReference ref = EcoreFactory.eINSTANCE.createEReference();
+ ref.setName("ref"); //$NON-NLS-1$
+ ref.setEType(eClass);
+ eClass.getEStructuralFeatures().add(ref);
+ pkg.getEClassifiers().add(eClass);
+ final Resource resource = new EcoreResourceFactoryImpl().createResource(URI.createURI(pkg.getNsURI()));
+ resource.getContents().add(pkg);
+
+ thrown.expect(DatabindingFailedException.class);
+ thrown.expectMessage("path reference Gone.ref (http://www.eclipse.org/ecp/test/gone)"); //$NON-NLS-1$
+ thrown.expectMessage(find(
+ "DMR VFeaturePathDomainModelReferenceImpl@\\p{XDigit}+ \\(changeListener: null\\)<VIRTUAL_URI\\.xmi#theDMR>")); //$NON-NLS-1$
+ thrown.expectMessage("is a proxy"); //$NON-NLS-1$
+
+ final D d = (D) createValidEObject(TestPackage.Literals.D);
+ final VFeaturePathDomainModelReference reference = createValidDMR();
+ reference.getDomainModelEReferencePath().add(ref);
+ reference.setDomainModelEFeature(TestPackage.Literals.A__B);
+
+ // Unload the package to proxify everything
+ resource.unload();
+
+ converter.getSetting(reference, d);
+ }
+
+ @Test
+ public void testGetSettingListReferenceInPath() throws DatabindingFailedException {
+ thrown.expect(DatabindingFailedException.class);
+ thrown.expectMessage("not a single reference: B.cList (test)"); //$NON-NLS-1$
+ thrown.expectMessage("DMR is VFeaturePathDomainModelReferenceImpl@"); //$NON-NLS-1$
+ thrown.expectMessage(
+ find("resolved EObject is BImpl@\\p{XDigit}+<VIRTUAL_URI\\.xmi#//@b>")); //$NON-NLS-1$
+
+ final VFeaturePathDomainModelReference pathReference = VViewFactory.eINSTANCE
+ .createFeaturePathDomainModelReference();
+ // create reference path to the attribute
+ final LinkedList<EReference> referencePath = new LinkedList<EReference>();
+ referencePath.add(TestPackage.Literals.A__B);
+ referencePath.add(TestPackage.Literals.B__CLIST);
+ referencePath.add(TestPackage.Literals.C__D);
+
+ pathReference.getDomainModelEReferencePath().addAll(referencePath);
+ pathReference.setDomainModelEFeature(TestPackage.Literals.D__X);
+
+ final A a = (A) createValidEObject(TestPackage.Literals.A);
+ final B b = TestFactory.eINSTANCE.createB();
+ a.setB(b);
+ converter.getSetting(pathReference, a);
+ }
+
+ @Test
+ public void testGetSettingMissingObjectInPath() throws DatabindingFailedException {
+ thrown.expect(DatabindingFailedException.class);
+ thrown.expectMessage("DMR is VFeaturePathDomainModelReferenceImpl@"); //$NON-NLS-1$
+ thrown.expectMessage(
+ find("resolved EObject is BImpl@\\p{XDigit}+<VIRTUAL_URI\\.xmi#//@b>")); //$NON-NLS-1$
+ thrown.expectMessage("Reference being resolved is B.c (test)"); //$NON-NLS-1$
+
+ final VFeaturePathDomainModelReference pathReference = VViewFactory.eINSTANCE
+ .createFeaturePathDomainModelReference();
+ // create reference path to the attribute
+ final LinkedList<EReference> referencePath = new LinkedList<EReference>();
+ referencePath.add(TestPackage.Literals.A__B);
+ referencePath.add(TestPackage.Literals.B__C);
+ referencePath.add(TestPackage.Literals.C__D);
+
+ pathReference.getDomainModelEReferencePath().addAll(referencePath);
+ pathReference.setDomainModelEFeature(TestPackage.Literals.D__X);
+
+ final A a = (A) createValidEObject(TestPackage.Literals.A);
+ final B b = TestFactory.eINSTANCE.createB();
+ a.setB(b);
+ converter.getSetting(pathReference, a);
+ }
+
+ @Test
+ public void testGetSettingFeatureHasNoType() throws DatabindingFailedException {
+ final EPackage pkg = EcoreFactory.eINSTANCE.createEPackage();
+ pkg.setName("untyped"); //$NON-NLS-1$
+ pkg.setNsPrefix("ut"); //$NON-NLS-1$
+ pkg.setNsURI("http://www.eclipse.org/ecp/test/untyped"); //$NON-NLS-1$
+ final EClass eClass = EcoreFactory.eINSTANCE.createEClass();
+ eClass.setName("Untyped"); //$NON-NLS-1$
+ final EReference ref = EcoreFactory.eINSTANCE.createEReference();
+ ref.setName("untyped"); //$NON-NLS-1$
+ // Don't set a type (that's the point)
+ eClass.getEStructuralFeatures().add(ref);
+ pkg.getEClassifiers().add(eClass);
+ final Resource resource = new EcoreResourceFactoryImpl().createResource(URI.createURI(pkg.getNsURI()));
+ resource.getContents().add(pkg);
+
+ thrown.expect(DatabindingFailedException.class);
+ thrown.expectMessage("in DMR VFeaturePathDomainModelReferenceImpl@"); //$NON-NLS-1$
+ thrown.expectMessage("eType of the feature Untyped.untyped (http://www.eclipse.org/ecp/test/untyped) is null"); //$NON-NLS-1$
+
+ final VFeaturePathDomainModelReference dmr = createValidDMR();
+ dmr.setDomainModelEFeature(ref);
+
+ final EObject untyped = createValidEObject(eClass);
+ converter.getSetting(dmr, untyped);
+ }
+
+ @Test
+ public void testGetSettingObjectDoesNotHaveFeature() throws DatabindingFailedException {
+ thrown.expect(DatabindingFailedException.class);
+ thrown.expectMessage(find("resolved EObject BImpl@\\p{XDigit}+<VIRTUAL_URI.xmi#/>")); //$NON-NLS-1$
+ thrown.expectMessage("doesn't have the feature C.d (test)"); //$NON-NLS-1$
+
+ final VFeaturePathDomainModelReference dmr = createValidDMR();
+ dmr.setDomainModelEFeature(TestPackage.Literals.C__D);
+
+ final EObject b = createValidEObject(TestPackage.Literals.B);
+ converter.getSetting(dmr, b);
+ }
+
}