Merge branch 'master' into bugs/401804
diff --git a/examples/org.eclipse.uml2.examples.uml.ui/src/org/eclipse/uml2/examples/uml/ui/dialogs/Ecore2UMLConverterOptionsDialog.java b/examples/org.eclipse.uml2.examples.uml.ui/src/org/eclipse/uml2/examples/uml/ui/dialogs/Ecore2UMLConverterOptionsDialog.java
index ff5556a..9d99726 100644
--- a/examples/org.eclipse.uml2.examples.uml.ui/src/org/eclipse/uml2/examples/uml/ui/dialogs/Ecore2UMLConverterOptionsDialog.java
+++ b/examples/org.eclipse.uml2.examples.uml.ui/src/org/eclipse/uml2/examples/uml/ui/dialogs/Ecore2UMLConverterOptionsDialog.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013 IBM Corporation, CEA, and others.
+ * Copyright (c) 2005, 2014 IBM Corporation, CEA, and others.
  * All rights reserved.   This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -8,6 +8,7 @@
  * Contributors:
  *   IBM - initial API and implementation
  *   Kenn Hussey (CEA) - 316165
+ *   Christian W. Damus (CEA) - 420338
  *
  */
 package org.eclipse.uml2.examples.uml.ui.dialogs;
@@ -85,5 +86,13 @@
 			UMLExamplesUIPlugin.INSTANCE.getString("_UI_XMIIdentifiers_label"), //$NON-NLS-1$
 			UMLUtil.Ecore2UMLConverter.OPTION__XMI_IDENTIFIERS, new String[]{
 				ignoreChoiceLabel, processChoiceLabel}, ignoreChoiceLabel);
+
+		createOptionArea(
+			parent,
+			UMLExamplesUIPlugin.INSTANCE
+				.getString("_UI_OppositeRoleNames_label"), //$NON-NLS-1$
+			UMLUtil.Ecore2UMLConverter.OPTION__OPPOSITE_ROLE_NAMES,
+			new String[]{ignoreChoiceLabel, processChoiceLabel},
+			ignoreChoiceLabel);
 	}
 }
diff --git a/examples/org.eclipse.uml2.examples.uml.ui/src/org/eclipse/uml2/examples/uml/ui/dialogs/UML2EcoreConverterOptionsDialog.java b/examples/org.eclipse.uml2.examples.uml.ui/src/org/eclipse/uml2/examples/uml/ui/dialogs/UML2EcoreConverterOptionsDialog.java
index 9c2670b..5fcc9b6 100644
--- a/examples/org.eclipse.uml2.examples.uml.ui/src/org/eclipse/uml2/examples/uml/ui/dialogs/UML2EcoreConverterOptionsDialog.java
+++ b/examples/org.eclipse.uml2.examples.uml.ui/src/org/eclipse/uml2/examples/uml/ui/dialogs/UML2EcoreConverterOptionsDialog.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013 IBM Corporation, Embarcadero Technologies, CEA, and others.
+ * Copyright (c) 2005, 2014 IBM Corporation, Embarcadero Technologies, CEA, and others.
  * All rights reserved.   This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,7 +9,7 @@
  *   IBM - initial API and implementation
  *   Kenn Hussey (Embarcadero Technologies) - 213218
  *   Kenn Hussey (CEA) - 322715
- *   Christian W. Damus (CEA) - 409396, 403374
+ *   Christian W. Damus (CEA) - 409396, 403374, 420338
  *
  */
 package org.eclipse.uml2.examples.uml.ui.dialogs;
@@ -187,6 +187,14 @@
 			UMLUtil.UML2EcoreConverter.OPTION__UNTYPED_PROPERTIES,
 			new String[]{ignoreChoiceLabel, reportChoiceLabel,
 				discardChoiceLabel, processChoiceLabel}, reportChoiceLabel);
+
+		createOptionArea(
+			parent,
+			UMLExamplesUIPlugin.INSTANCE
+				.getString("_UI_OppositeRoleNames_label"), //$NON-NLS-1$
+			UMLUtil.UML2EcoreConverter.OPTION__OPPOSITE_ROLE_NAMES,
+			new String[]{ignoreChoiceLabel, processChoiceLabel},
+			ignoreChoiceLabel);
 	}
 
 }
diff --git a/plugins/org.eclipse.uml2.uml.ecore.exporter/src/org/eclipse/uml2/uml/ecore/exporter/ui/UMLExporterOptionsPage.java b/plugins/org.eclipse.uml2.uml.ecore.exporter/src/org/eclipse/uml2/uml/ecore/exporter/ui/UMLExporterOptionsPage.java
index 1ff7bbb..7bdc4e9 100644
--- a/plugins/org.eclipse.uml2.uml.ecore.exporter/src/org/eclipse/uml2/uml/ecore/exporter/ui/UMLExporterOptionsPage.java
+++ b/plugins/org.eclipse.uml2.uml.ecore.exporter/src/org/eclipse/uml2/uml/ecore/exporter/ui/UMLExporterOptionsPage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2013 IBM Corporation, CEA, and others.
+ * Copyright (c) 2006, 2014 IBM Corporation, CEA, and others.
  * All rights reserved.   This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -8,6 +8,7 @@
  * Contributors:
  *   IBM - initial API and implementation
  *   Kenn Hussey (CEA) - 316165
+ *   Christian W. Damus (CEA) - 420338
  *
  */
 package org.eclipse.uml2.uml.ecore.exporter.ui;
@@ -179,6 +180,12 @@
 			UMLExporterPlugin.INSTANCE.getString("_UI_XMIIdentifiers_label"), //$NON-NLS-1$
 			UMLUtil.Ecore2UMLConverter.OPTION__XMI_IDENTIFIERS, new String[]{
 				ignoreChoiceLabel, processChoiceLabel}, ignoreChoiceLabel);
+		addOptionControl(
+			optionsComposite,
+			UMLExporterPlugin.INSTANCE.getString("_UI_OppositeRoleNames_label"), //$NON-NLS-1$
+			UMLUtil.Ecore2UMLConverter.OPTION__OPPOSITE_ROLE_NAMES,
+			new String[]{ignoreChoiceLabel, processChoiceLabel},
+			ignoreChoiceLabel);
 
 		scrolledComposite.setContent(optionsComposite);
 		scrolledComposite.setExpandHorizontal(true);
diff --git a/plugins/org.eclipse.uml2.uml.ecore.importer/src/org/eclipse/uml2/uml/ecore/importer/UMLImporterApplication.java b/plugins/org.eclipse.uml2.uml.ecore.importer/src/org/eclipse/uml2/uml/ecore/importer/UMLImporterApplication.java
index ee1bc76..5cb03ff 100644
--- a/plugins/org.eclipse.uml2.uml.ecore.importer/src/org/eclipse/uml2/uml/ecore/importer/UMLImporterApplication.java
+++ b/plugins/org.eclipse.uml2.uml.ecore.importer/src/org/eclipse/uml2/uml/ecore/importer/UMLImporterApplication.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013 IBM Corporation, Embarcadero Technologies, CEA, and others.
+ * Copyright (c) 2007, 2014 IBM Corporation, Embarcadero Technologies, CEA, and others.
  * All rights reserved.   This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,7 +9,7 @@
  *   IBM - initial API and implementation
  *   Kenn Hussey (Embarcadero Technologies) - 213218
  *   Kenn Hussey (CEA) - 322715
- *   Christian W. Damus (CEA) - 403374
+ *   Christian W. Damus (CEA) - 403374, 420338
  *
  */
 package org.eclipse.uml2.uml.ecore.importer;
@@ -102,7 +102,7 @@
 		appendLine(result,"                               -SUBSETTING_PROPERTIES | -UNION_PROPERTIES | -DERIVED_FEATURES |" ); //$NON-NLS-1$
 		appendLine(result,"                               -DUPLICATE_OPERATIONS | -DUPLICATE_OPERATION_INHERITANCE |" ); //$NON-NLS-1$
 		appendLine(result,"                               -DUPLICATE_FEATURES | -DUPLICATE_FEATURE_INHERITANCE |" ); //$NON-NLS-1$
-		appendLine(result,"                               -UNTYPED_PROPERTIES |"); //$NON-NLS-1$
+		appendLine(result,"                               -UNTYPED_PROPERTIES | -OPPOSITE_ROLE_NAMES |"); //$NON-NLS-1$
 		appendLine(result,"                               -SUPER_CLASS_ORDER | -ANNOTATION_DETAILS |" ); //$NON-NLS-1$
 		appendLine(result,"                               -INVARIANT_CONSTRAINTS | -VALIDATION_DELEGATES | -NON_API_INVARIANTS |" ); //$NON-NLS-1$
 		appendLine(result,"                               -OPERATION_BODIES | -INVOCATION_DELEGATES |" ); //$NON-NLS-1$
@@ -200,6 +200,8 @@
 			|| UMLUtil.UML2EcoreConverter.OPTION__COMMENTS
 				.equalsIgnoreCase(strippedKey)
 			|| UMLUtil.UML2EcoreConverter.OPTION__CAMEL_CASE_NAMES
+				.equalsIgnoreCase(strippedKey)
+			|| UMLUtil.UML2EcoreConverter.OPTION__OPPOSITE_ROLE_NAMES
 				.equalsIgnoreCase(strippedKey);
 	}
 
diff --git a/plugins/org.eclipse.uml2.uml.ecore.importer/src/org/eclipse/uml2/uml/ecore/importer/ui/UMLImporterDetailPage.java b/plugins/org.eclipse.uml2.uml.ecore.importer/src/org/eclipse/uml2/uml/ecore/importer/ui/UMLImporterDetailPage.java
index f4ba38f..aafc551 100644
--- a/plugins/org.eclipse.uml2.uml.ecore.importer/src/org/eclipse/uml2/uml/ecore/importer/ui/UMLImporterDetailPage.java
+++ b/plugins/org.eclipse.uml2.uml.ecore.importer/src/org/eclipse/uml2/uml/ecore/importer/ui/UMLImporterDetailPage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2013 IBM Corporation, Embarcadero Technologies, CEA, and others.
+ * Copyright (c) 2006, 2014 IBM Corporation, Embarcadero Technologies, CEA, and others.
  * All rights reserved.   This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,7 +9,7 @@
  *   IBM - initial API and implementation
  *   Kenn Hussey (Embarcadero Technologies) - 213218
  *   Kenn Hussey (CEA) - 322715
- *   Christian W. Damus (CEA) - 409396, 403374
+ *   Christian W. Damus (CEA) - 409396, 403374, 420338
  *
  */
 package org.eclipse.uml2.uml.ecore.importer.ui;
@@ -268,6 +268,12 @@
 			UMLUtil.UML2EcoreConverter.OPTION__UNTYPED_PROPERTIES,
 			new String[]{ignoreChoiceLabel, reportChoiceLabel,
 				discardChoiceLabel, processChoiceLabel}, reportChoiceLabel);
+		addOptionControl(
+			optionsComposite,
+			UMLImporterPlugin.INSTANCE.getString("_UI_OppositeRoleNames_label"), //$NON-NLS-1$
+			UMLUtil.UML2EcoreConverter.OPTION__OPPOSITE_ROLE_NAMES,
+			new String[]{ignoreChoiceLabel, processChoiceLabel},
+			ignoreChoiceLabel);
 
 		scrolledComposite.setContent(optionsComposite);
 		scrolledComposite.setExpandHorizontal(true);
diff --git a/plugins/org.eclipse.uml2.uml.editor/src/org/eclipse/uml2/uml/editor/dialogs/Profile2EPackageConverterOptionsDialog.java b/plugins/org.eclipse.uml2.uml.editor/src/org/eclipse/uml2/uml/editor/dialogs/Profile2EPackageConverterOptionsDialog.java
index 71a66e6..71fdc1b 100644
--- a/plugins/org.eclipse.uml2.uml.editor/src/org/eclipse/uml2/uml/editor/dialogs/Profile2EPackageConverterOptionsDialog.java
+++ b/plugins/org.eclipse.uml2.uml.editor/src/org/eclipse/uml2/uml/editor/dialogs/Profile2EPackageConverterOptionsDialog.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013 IBM Corporation, CEA, and others.
+ * Copyright (c) 2007, 2014 IBM Corporation, CEA, and others.
  * All rights reserved.   This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -8,7 +8,7 @@
  * Contributors:
  *   IBM - initial API and implementation
  *   Kenn Hussey (CEA) - 322715, 163556
- *   Christian W. Damus (CEA) - 409396, 403374
+ *   Christian W. Damus (CEA) - 409396, 403374, 420338
  *
  */
 package org.eclipse.uml2.uml.editor.dialogs;
@@ -177,5 +177,12 @@
 			UMLUtil.Profile2EPackageConverter.OPTION__UNTYPED_PROPERTIES,
 			new String[]{ignoreChoiceLabel, reportChoiceLabel,
 				discardChoiceLabel, processChoiceLabel}, reportChoiceLabel);
+
+		createOptionArea(
+			parent,
+			UMLEditorPlugin.INSTANCE.getString("_UI_OppositeRoleNames_label"), //$NON-NLS-1$
+			UMLUtil.UML2EcoreConverter.OPTION__OPPOSITE_ROLE_NAMES,
+			new String[]{ignoreChoiceLabel, processChoiceLabel},
+			ignoreChoiceLabel);
 	}
 }
diff --git a/plugins/org.eclipse.uml2.uml/model/UML.genmodel b/plugins/org.eclipse.uml2.uml/model/UML.genmodel
index b3b77fd..4b84ceb 100644
--- a/plugins/org.eclipse.uml2.uml/model/UML.genmodel
+++ b/plugins/org.eclipse.uml2.uml/model/UML.genmodel
@@ -32,6 +32,7 @@
     <details key="INVOCATION_DELEGATES" value="IGNORE"/>
     <details key="UNTYPED_PROPERTIES" value="REPORT"/>
     <details key="NON_API_INVARIANTS" value="IGNORE"/>
+    <details key="OPPOSITE_ROLE_NAMES" value="IGNORE"/>
   </genAnnotations>
   <foreignModel>UML.merged.uml</foreignModel>
   <genPackages xsi:type="genmodel:GenPackage" prefix="UML" basePackage="org.eclipse.uml2"
diff --git a/plugins/org.eclipse.uml2.uml/plugin.properties b/plugins/org.eclipse.uml2.uml/plugin.properties
index c2fd579..4527a74 100644
--- a/plugins/org.eclipse.uml2.uml/plugin.properties
+++ b/plugins/org.eclipse.uml2.uml/plugin.properties
@@ -1,4 +1,4 @@
-# Copyright (c) 2005, 2013 IBM Corporation, Embarcadero Technologies, CEA, and others.
+# Copyright (c) 2005, 2014 IBM Corporation, Embarcadero Technologies, CEA, and others.
 # All rights reserved.   This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
 # which accompanies this distribution, and is available at
@@ -8,7 +8,7 @@
 #   IBM - initial API and implementation
 #   Kenn Hussey (Embarcadero Technologies) - 156879, 215488, 213218, 204200
 #   Kenn Hussey (CEA) - 327039, 351774, 373709, 388636, 295864, 397140, 316165, 322715, 80307, 416833
-#   Christian W. Damus (CEA) - 373643, 374012, 163556, 409396, 180744, 403374
+#   Christian W. Damus (CEA) - 373643, 374012, 163556, 409396, 180744, 403374, 420338
 #
 
 # NLS_MESSAGEFORMAT_VAR
@@ -78,6 +78,7 @@
 _UI_UML2EcoreConverter_ReportSuperClassOrder_diagnostic = The super classes of class ''{0}'' should be re-ordered for optimal code generation.
 _UI_UML2EcoreConverter_ReportAnnotationDetails_diagnostic = Model element ''{0}'' should be annotated with details from source ''{1}''.
 _UI_UML2EcoreConverter_ReportUntypedProperty_diagnostic = Feature ''{0}'' has no type specified.
+_UI_UML2EcoreConverter_ProcessOppositeRoleName_diagnostic = Reference ''{0}'' has been annotated with opposite role name ''{1}''.
 
 _UI_Ecore2UMLConverter_ProcessEcoreTaggedValue_diagnostic = Applied Ecore tag ''{1}'' with value of ''{2}'' to element ''{0}''.
 _UI_Ecore2UMLConverter_ProcessRedefinesAnnotation_diagnostic = Made ''{0}'' redefine ''{1}'' based on an annotation.
@@ -90,6 +91,7 @@
 _UI_Ecore2UMLConverter_ReportSubsetsAnnotation_diagnostic = ''{0}'' should subset ''{1}'' based on an annotation.
 _UI_Ecore2UMLConverter_ReportUnionAnnotation_diagnostic = ''{0}'' should be a union based on an annotation.
 _UI_Ecore2UMLConverter_ReportAnnotationDetails_diagnostic = Element ''{0}'' should be annotated with details from source ''{1}''.
+_UI_Ecore2UMLConverter_ProcessOppositeRoleName_diagnostic = Property ''{0}'' association-owned opposite has been named ''{1}''.
 
 _UI_Classifier_NoCyclesInGeneralization_diagnostic = Classifier ''{0}'' is both a transitively general and transitively specific classifier of the same classifier.
 _UI_Classifier_SpecializeType_diagnostic = Classifier ''{0}'' specializes classifier ''{1}'' of invalid type.
@@ -205,6 +207,7 @@
 _UI_OperationBodies_label = Operation Bodies
 _UI_Comments_label = Comments
 _UI_UntypedProperties_label = Untyped Properties
+_UI_OppositeRoleNames_label = Opposite Role Names
 
 _UI_RedefinesAnnotations_label = Redefines Annotations
 _UI_SubsetsAnnotations_label = Subsets Annotations
diff --git a/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/util/UMLUtil.java b/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/util/UMLUtil.java
index 45ac700..bc1a892 100644
--- a/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/util/UMLUtil.java
+++ b/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/util/UMLUtil.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013 IBM Corporation, Embarcadero Technologies, CEA, and others.
+ * Copyright (c) 2005, 2014 IBM Corporation, Embarcadero Technologies, CEA, and others.
  * All rights reserved.   This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -12,7 +12,8 @@
  *   Kenn Hussey - 286329, 313601, 314971, 344907, 236184, 335125
  *   Kenn Hussey (CEA) - 327039, 358792, 364419, 366350, 307343, 382637, 273949, 389542, 389495, 316165, 392833, 399544, 322715, 163556, 212765, 397324, 204658, 408612, 411731, 269598, 422000, 416833
  *   Yann Tanguy (CEA) - 350402
- *   Christian W. Damus (CEA) - 392833, 251963, 405061, 409396, 176998, 180744, 403374, 416833
+ *   Christian W. Damus (CEA) - 392833, 251963, 405061, 409396, 176998, 180744, 403374, 416833, 420338
+ *   E.D.Willink - 420338
  *
  */
 package org.eclipse.uml2.uml.util;
@@ -68,6 +69,7 @@
 import org.eclipse.emf.ecore.util.EcoreUtil;
 import org.eclipse.emf.ecore.util.ExtendedMetaData;
 import org.eclipse.emf.ecore.util.InternalEList;
+import org.eclipse.emf.ecore.xmi.impl.EMOFExtendedMetaData;
 import org.eclipse.emf.ecore.xml.type.XMLTypePackage;
 import org.eclipse.uml2.common.util.CacheAdapter;
 import org.eclipse.uml2.common.util.UML2Util;
@@ -3827,6 +3829,14 @@
 		 */
 		public static final String OPTION__UNTYPED_PROPERTIES = "UNTYPED_PROPERTIES"; //$NON-NLS-1$
 
+		/**
+		 * The option for handling opposite role names. Supported choices are
+		 * {@code OPTION__IGNORE} and {@code OPTION__PROCESS}.
+		 * 
+		 * @since 4.2
+		 */
+		public static final String OPTION__OPPOSITE_ROLE_NAMES = "OPPOSITE_ROLE_NAMES"; //$NON-NLS-1$
+
 		private static final int DIAGNOSTIC_CODE_OFFSET = 2000;
 
 		/**
@@ -3927,6 +3937,14 @@
 		 */
 		public static final int UNTYPED_PROPERTY = DIAGNOSTIC_CODE_OFFSET + 17;
 
+		/**
+		 * The diagnostic code for notification of opposite role name
+		 * annotations.
+		 * 
+		 * @since 4.2
+		 */
+		public static final int OPPOSITE_ROLE_NAME = DIAGNOSTIC_CODE_OFFSET + 18;
+
 		protected static final Pattern ANNOTATION_PATTERN = Pattern
 			.compile("\\G\\s*((?>\\\\.|\\S)+)((?:\\s+(?>\\\\.|\\S)+\\s*+=\\s*(['\"])((?>\\\\.|.)*?)\\3)*)"); //$NON-NLS-1$
 
@@ -4909,7 +4927,7 @@
 
 						eAttribute.setDefaultValueLiteral(default_);
 					}
-					
+
 					eAttribute.setID(property.isID());
 				}
 
@@ -4941,6 +4959,43 @@
 						((EReference) eStructuralFeature)
 							.setEOpposite(eOpposite);
 					}
+				} else if ((eStructuralFeature instanceof EReference)
+					&& OPTION__PROCESS.equals(options
+						.get(OPTION__OPPOSITE_ROLE_NAMES))) {
+
+					Property otherEnd = property.getOtherEnd();
+
+					if (otherEnd != null) {
+						String explicitRoleName = otherEnd.getName();
+						String implicitRoleName = namespace.getName();
+
+						if (!isEmpty(explicitRoleName)
+							&& !explicitRoleName.equals(implicitRoleName)) {
+
+							EcoreUtil
+								.setAnnotation(
+									eStructuralFeature,
+									EMOFExtendedMetaData.EMOF_PROPERTY_OPPOSITE_ROLE_NAME_ANNOTATION_SOURCE,
+									EMOFExtendedMetaData.EMOF_COMMENT_BODY,
+									explicitRoleName);
+
+							if (diagnostics != null) {
+								diagnostics
+									.add(new BasicDiagnostic(
+										Diagnostic.INFO,
+										UMLValidator.DIAGNOSTIC_SOURCE,
+										OPPOSITE_ROLE_NAME,
+										UMLPlugin.INSTANCE
+											.getString(
+												"_UI_UML2EcoreConverter_ProcessOppositeRoleName_diagnostic", //$NON-NLS-1$
+												getMessageSubstitutions(
+													context,
+													eStructuralFeature,
+													explicitRoleName)),
+										new Object[]{eStructuralFeature}));
+							}
+						}
+					}
 				}
 
 				if (type != null) {
@@ -8081,6 +8136,14 @@
 		 */
 		public static final String OPTION__XMI_IDENTIFIERS = "XMI_IDENTIFIERS"; //$NON-NLS-1$
 
+		/**
+		 * The option for handling opposite role name annotations. Supported
+		 * choices are {@code OPTION__IGNORE} and {@code OPTION__PROCESS}.
+		 * 
+		 * @since 4.2
+		 */
+		public static final String OPTION__OPPOSITE_ROLE_NAMES = "OPPOSITE_ROLE_NAMES"; //$NON-NLS-1$
+
 		private static final int DIAGNOSTIC_CODE_OFFSET = 3000;
 
 		/**
@@ -8129,6 +8192,14 @@
 		 */
 		public static final int XMI_IDENTIFIER = DIAGNOSTIC_CODE_OFFSET + 8;
 
+		/**
+		 * The diagnostic code for cases where an opposite role name annotation
+		 * is encountered.
+		 * 
+		 * @since 4.2
+		 */
+		public static final int OPPOSITE_ROLE_NAME = DIAGNOSTIC_CODE_OFFSET + 9;
+
 		protected final Map<EModelElement, Element> eModelElementToElementMap = new LinkedHashMap<EModelElement, Element>();
 
 		protected Collection<EPackage> ePackages = null;
@@ -8873,7 +8944,37 @@
 
 					property.setAssociation(association);
 
-					association.createOwnedEnd(null, classifier);
+					Property opposite = association.createOwnedEnd(null,
+						classifier);
+
+					if (OPTION__PROCESS.equals(options
+						.get(OPTION__OPPOSITE_ROLE_NAMES))) {
+
+						String oppositeRoleName = EcoreUtil
+							.getAnnotation(
+								eReference,
+								EMOFExtendedMetaData.EMOF_PROPERTY_OPPOSITE_ROLE_NAME_ANNOTATION_SOURCE,
+								EMOFExtendedMetaData.EMOF_COMMENT_BODY);
+
+						if (oppositeRoleName != null) {
+							opposite.setName(oppositeRoleName);
+
+							if (diagnostics != null) {
+								diagnostics
+									.add(new BasicDiagnostic(
+										Diagnostic.INFO,
+										UMLValidator.DIAGNOSTIC_SOURCE,
+										OPPOSITE_ROLE_NAME,
+										UMLPlugin.INSTANCE
+											.getString(
+												"_UI_Ecore2UMLConverter_ProcessOppositeRoleName_diagnostic", //$NON-NLS-1$
+												getMessageSubstitutions(
+													context, property,
+													oppositeRoleName)),
+										new Object[]{property, opposite}));
+							}
+						}
+					}
 				} else {
 					Property opposite = (Property) doSwitch(eOpposite);
 
@@ -9337,6 +9438,8 @@
 						if (source != null
 							&& !source.equals(EcorePackage.eNS_URI)
 							&& !source.equals(ExtendedMetaData.ANNOTATION_URI)
+							&& !source
+								.equals(EMOFExtendedMetaData.EMOF_PROPERTY_OPPOSITE_ROLE_NAME_ANNOTATION_SOURCE)
 							&& !source.equals(EMF_GEN_MODEL_PACKAGE_NS_URI)
 							&& !source.equals(UML2_UML_PACKAGE_2_0_NS_URI)
 							&& !source.equals(ANNOTATION__DUPLICATES)
@@ -10263,6 +10366,8 @@
 						if (source != null
 							&& !source.equals(EcorePackage.eNS_URI)
 							&& !source.equals(ExtendedMetaData.ANNOTATION_URI)
+							&& !source
+								.equals(EMOFExtendedMetaData.EMOF_PROPERTY_OPPOSITE_ROLE_NAME_ANNOTATION_SOURCE)
 							&& !source.equals(EMF_GEN_MODEL_PACKAGE_NS_URI)
 							&& !source.equals(UML2_UML_PACKAGE_2_0_NS_URI)
 							&& !source.equals(ANNOTATION__DUPLICATES)
@@ -11979,6 +12084,13 @@
 				OPTION__IGNORE);
 		}
 
+		if (!options
+			.containsKey(UML2EcoreConverter.OPTION__OPPOSITE_ROLE_NAMES)) {
+
+			options.put(UML2EcoreConverter.OPTION__OPPOSITE_ROLE_NAMES,
+				OPTION__IGNORE);
+		}
+
 		return convertToEcore(package_, options, null, null);
 	}
 
@@ -12243,6 +12355,13 @@
 				OPTION__IGNORE);
 		}
 
+		if (!options
+			.containsKey(UML2EcoreConverter.OPTION__OPPOSITE_ROLE_NAMES)) {
+
+			options.put(UML2EcoreConverter.OPTION__OPPOSITE_ROLE_NAMES,
+				OPTION__IGNORE);
+		}
+
 		return convertToEcore(profile, options, null, null);
 	}
 
diff --git a/tests/org.eclipse.uml2.uml.tests/src/org/eclipse/uml2/uml/bug/tests/Bug420338.uml b/tests/org.eclipse.uml2.uml.tests/src/org/eclipse/uml2/uml/bug/tests/Bug420338.uml
new file mode 100644
index 0000000..7a08413
--- /dev/null
+++ b/tests/org.eclipse.uml2.uml.tests/src/org/eclipse/uml2/uml/bug/tests/Bug420338.uml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<uml:Package xmi:version="20110701" xmlns:xmi="http://www.omg.org/spec/XMI/20110701" xmlns:uml="http://www.eclipse.org/uml2/4.0.0/UML" xmi:id="_3rGvcHSWEeOCP45ZAzv7Qw" name="bug420338" URI="http://www.eclipse.org/uml2/tests/bugs/420338">
+  <packagedElement xmi:type="uml:Class" xmi:id="_3wDEYHSXEeOy8Nli9HVgSQ" name="A">
+    <ownedAttribute xmi:id="_79euIHSXEeOy8Nli9HVgSQ" name="b" type="_4yTLkHSXEeOy8Nli9HVgSQ" association="_-fafYHSXEeOy8Nli9HVgSQ"/>
+  </packagedElement>
+  <packagedElement xmi:type="uml:Class" xmi:id="_4yTLkHSXEeOy8Nli9HVgSQ" name="B"/>
+  <packagedElement xmi:type="uml:Association" xmi:id="_-fafYHSXEeOy8Nli9HVgSQ" memberEnd="_79euIHSXEeOy8Nli9HVgSQ _CZu_4HSYEeOy8Nli9HVgSQ">
+    <ownedEnd xmi:id="_CZu_4HSYEeOy8Nli9HVgSQ" name="theA" type="_3wDEYHSXEeOy8Nli9HVgSQ" association="_-fafYHSXEeOy8Nli9HVgSQ"/>
+  </packagedElement>
+  <packagedElement xmi:type="uml:Class" xmi:id="_Gvh7cHSYEeOy8Nli9HVgSQ" name="M">
+    <ownedAttribute xmi:id="_Gvh7cXSYEeOy8Nli9HVgSQ" name="n" type="_Gvh7cnSYEeOy8Nli9HVgSQ" association="_Gvh7c3SYEeOy8Nli9HVgSQ"/>
+  </packagedElement>
+  <packagedElement xmi:type="uml:Class" xmi:id="_Gvh7cnSYEeOy8Nli9HVgSQ" name="N"/>
+  <packagedElement xmi:type="uml:Association" xmi:id="_Gvh7c3SYEeOy8Nli9HVgSQ" memberEnd="_Gvh7cXSYEeOy8Nli9HVgSQ _Gvh7dHSYEeOy8Nli9HVgSQ">
+    <ownedEnd xmi:id="_Gvh7dHSYEeOy8Nli9HVgSQ" type="_Gvh7cHSYEeOy8Nli9HVgSQ" association="_Gvh7c3SYEeOy8Nli9HVgSQ"/>
+  </packagedElement>
+  <packagedElement xmi:type="uml:Class" xmi:id="_lCli4HSbEeO7FvYuyvhJVg" name="S">
+    <ownedAttribute xmi:id="_lCli4XSbEeO7FvYuyvhJVg" name="t" type="_lCli4nSbEeO7FvYuyvhJVg" association="_lCli43SbEeO7FvYuyvhJVg"/>
+  </packagedElement>
+  <packagedElement xmi:type="uml:Class" xmi:id="_lCli4nSbEeO7FvYuyvhJVg" name="T">
+    <ownedAttribute xmi:id="_lCli5HSbEeO7FvYuyvhJVg" name="s" type="_lCli4HSbEeO7FvYuyvhJVg" association="_lCli43SbEeO7FvYuyvhJVg"/>
+  </packagedElement>
+  <packagedElement xmi:type="uml:Association" xmi:id="_lCli43SbEeO7FvYuyvhJVg" memberEnd="_lCli4XSbEeO7FvYuyvhJVg _lCli5HSbEeO7FvYuyvhJVg"/>
+  <packagedElement xmi:type="uml:Class" xmi:id="_S6xwUHSYEeOy8Nli9HVgSQ" name="X">
+    <ownedAttribute xmi:id="_S6xwUXSYEeOy8Nli9HVgSQ" name="y" type="_S6xwUnSYEeOy8Nli9HVgSQ"/>
+  </packagedElement>
+  <packagedElement xmi:type="uml:Class" xmi:id="_S6xwUnSYEeOy8Nli9HVgSQ" name="Y"/>
+</uml:Package>
diff --git a/tests/org.eclipse.uml2.uml.tests/src/org/eclipse/uml2/uml/bug/tests/Bug420338Test.java b/tests/org.eclipse.uml2.uml.tests/src/org/eclipse/uml2/uml/bug/tests/Bug420338Test.java
new file mode 100644
index 0000000..dc043fb
--- /dev/null
+++ b/tests/org.eclipse.uml2.uml.tests/src/org/eclipse/uml2/uml/bug/tests/Bug420338Test.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2013, 2014 CEA and others.
+ * 
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   Christian W. Damus (CEA) - Initial API and implementation
+ *
+ */
+package org.eclipse.uml2.uml.bug.tests;
+
+import java.net.URL;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EPackage;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.resource.Resource;
+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.impl.EMOFExtendedMetaData;
+import org.eclipse.uml2.common.util.UML2Util;
+import org.eclipse.uml2.uml.Package;
+import org.eclipse.uml2.uml.Property;
+import org.eclipse.uml2.uml.Type;
+import org.eclipse.uml2.uml.UMLPackage;
+import org.eclipse.uml2.uml.tests.util.StandaloneSupport;
+import org.eclipse.uml2.uml.util.UMLUtil;
+
+/**
+ * Tests the support for UML-to-Ecore and Ecore-to-UML transformation of
+ * non-navigable association ends for OCL support.
+ * 
+ * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=420338
+ */
+public class Bug420338Test
+		extends TestCase {
+
+	private ResourceSet rset;
+
+	private Package fixture;
+
+	private EPackage eFixture;
+
+	public Bug420338Test() {
+		super();
+	}
+
+	public Bug420338Test(String name) {
+		super(name);
+	}
+
+	public static Test suite() {
+		return new TestSuite(Bug420338Test.class, "Bug 420338 tests"); //$NON-NLS-1$
+	}
+
+	public void testExplicitRoleName_nonNavigable() {
+		convertToEcore();
+
+		EReference b = getEReference(getEClass("A"), "b");
+		assertOppositeRoleName(b, "theA");
+
+		convertToUML();
+
+		Property b_ = getClass("A").getOwnedAttribute("b", null);
+		assertOppositeRoleName(b_, "theA");
+	}
+
+	public void testImplicitRoleName_nonNavigable() {
+		convertToEcore();
+
+		EReference n = getEReference(getEClass("M"), "n");
+		assertNoOppositeRoleName(n);
+
+		convertToUML();
+
+		Property n_ = getClass("M").getOwnedAttribute("n", null);
+		assertNoOppositeRoleName(n_);
+	}
+
+	public void testExplicitRoleName_navigable() {
+		convertToEcore();
+
+		EReference t = getEReference(getEClass("S"), "t");
+		assertNoOppositeRoleName(t);
+
+		convertToUML();
+
+		Property t_ = getClass("S").getOwnedAttribute("t", null);
+		assertOppositeRoleName(t_, "s");
+	}
+
+	public void testImplicitRoleName_noAssociation() {
+		convertToEcore();
+
+		EReference y = getEReference(getEClass("X"), "y");
+		assertNoOppositeRoleName(y);
+
+		convertToUML();
+
+		Property y_ = getClass("X").getOwnedAttribute("y", null);
+		assertNoOppositeRoleName(y_);
+	}
+
+	//
+	// Test framework
+	//
+
+	@Override
+	protected void setUp()
+			throws Exception {
+
+		rset = new ResourceSetImpl();
+		if (StandaloneSupport.isStandalone()) {
+			StandaloneSupport.init(rset);
+		}
+
+		fixture = getTestModel();
+	}
+
+	@Override
+	protected void tearDown()
+			throws Exception {
+
+		fixture = null;
+		eFixture = null;
+
+		// clean up the CacheAdapter as well as we can
+		for (Resource next : rset.getResources()) {
+			next.unload();
+			next.eAdapters().clear();
+		}
+
+		rset.getResources().clear();
+		rset.eAdapters().clear();
+	}
+
+	Package getTestModel() {
+		URL url = getClass().getResource("Bug420338.uml"); //$NON-NLS-1$
+		return (Package) UML2Util.load(rset,
+			URI.createURI(url.toExternalForm()), UMLPackage.Literals.PACKAGE);
+	}
+
+	void convertToEcore() {
+		eFixture = convert(fixture);
+	}
+
+	EPackage convert(Package package_) {
+		Map<String, String> options = new HashMap<String, String>();
+		options.put(UMLUtil.UML2EcoreConverter.OPTION__OPPOSITE_ROLE_NAMES,
+			UMLUtil.OPTION__PROCESS);
+
+		Collection<EPackage> ecores = UMLUtil.convertToEcore(package_, options);
+
+		assertNotNull(ecores);
+		assertTrue(ecores.size() > 0);
+
+		// we need to be able to clean these up, later
+		for (EPackage next : ecores) {
+			if (next.eResource() == null) {
+				Resource res = rset.createResource(URI.createURI(String.format(
+					"http:///%s.ecore", System.identityHashCode(next))));
+				res.getContents().add(next);
+			}
+		}
+
+		EPackage result = ecores.iterator().next();
+		assertEquals("bug420338", result.getName());
+
+		return result;
+	}
+
+	void convertToUML() {
+		fixture = convert(eFixture);
+	}
+
+	Package convert(EPackage ePackage) {
+		Map<String, String> options = new HashMap<String, String>();
+		options.put(UMLUtil.Ecore2UMLConverter.OPTION__OPPOSITE_ROLE_NAMES,
+			UMLUtil.OPTION__PROCESS);
+
+		Collection<Package> umls = UMLUtil.convertFromEcore(ePackage, options);
+
+		assertNotNull(umls);
+		assertTrue(umls.size() > 0);
+
+		// we need to be able to clean these up, later
+		for (Package next : umls) {
+			if (next.eResource() == null) {
+				Resource res = rset.createResource(URI.createURI(String.format(
+					"http:///%s.uml", System.identityHashCode(next))));
+				res.getContents().add(next);
+			}
+		}
+
+		Package result = umls.iterator().next();
+		assertEquals("bug420338", result.getName());
+
+		return result;
+	}
+
+	EClass getEClass(String name) {
+		return getEClass(eFixture, name);
+	}
+
+	EClass getEClass(EPackage ePackage, String name) {
+		return getEClassifier(ePackage, name, EClass.class);
+	}
+
+	<T extends EClassifier> T getEClassifier(EPackage ePackage, String name,
+			Class<T> metaclass) {
+		EClassifier result = ePackage.getEClassifier(name);
+		assertTrue(metaclass.isInstance(result));
+		return metaclass.cast(result);
+	}
+
+	EReference getEReference(EClass eClass, String name) {
+		return getEStructuralFeature(eClass, name, EReference.class);
+	}
+
+	<T extends EStructuralFeature> T getEStructuralFeature(EClass eClass,
+			String name, Class<T> metaclass) {
+
+		EStructuralFeature result = eClass.getEStructuralFeature(name);
+		assertTrue(metaclass.isInstance(result));
+		return metaclass.cast(result);
+	}
+
+	org.eclipse.uml2.uml.Class getClass(String name) {
+		return getClass(fixture, name);
+	}
+
+	org.eclipse.uml2.uml.Class getClass(Package package_, String name) {
+		return getType(package_, name, org.eclipse.uml2.uml.Class.class);
+	}
+
+	<T extends Type> T getType(Package package_, String name, Class<T> metaclass) {
+		Type result = package_.getOwnedType(name);
+		assertTrue(metaclass.isInstance(result));
+		return metaclass.cast(result);
+	}
+
+	void assertOppositeRoleName(EReference reference, String roleName) {
+		String actual = EcoreUtil
+			.getAnnotation(
+				reference,
+				EMOFExtendedMetaData.EMOF_PROPERTY_OPPOSITE_ROLE_NAME_ANNOTATION_SOURCE,
+				EMOFExtendedMetaData.EMOF_COMMENT_BODY);
+		assertEquals(roleName, actual);
+	}
+
+	void assertNoOppositeRoleName(EReference reference) {
+		String actual = EcoreUtil
+			.getAnnotation(
+				reference,
+				EMOFExtendedMetaData.EMOF_PROPERTY_OPPOSITE_ROLE_NAME_ANNOTATION_SOURCE,
+				EMOFExtendedMetaData.EMOF_COMMENT_BODY);
+		assertNull(actual);
+	}
+
+	void assertOppositeRoleName(Property property, String roleName) {
+		assertNotNull(property);
+		Property opposite = property.getOtherEnd();
+		assertNotNull(opposite);
+		assertEquals(roleName, opposite.getName());
+	}
+
+	void assertNoOppositeRoleName(Property property) {
+		assertNotNull(property);
+		Property opposite = property.getOtherEnd();
+		assertNotNull(opposite); // Ecore-to-UML always creates an association
+		assertNull(opposite.getName());
+	}
+
+}
diff --git a/tests/org.eclipse.uml2.uml.tests/src/org/eclipse/uml2/uml/bug/tests/UMLBugTests.java b/tests/org.eclipse.uml2.uml.tests/src/org/eclipse/uml2/uml/bug/tests/UMLBugTests.java
index ac2e06a..b3c807d 100644
--- a/tests/org.eclipse.uml2.uml.tests/src/org/eclipse/uml2/uml/bug/tests/UMLBugTests.java
+++ b/tests/org.eclipse.uml2.uml.tests/src/org/eclipse/uml2/uml/bug/tests/UMLBugTests.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 CEA and others.
+ * Copyright (c) 2013, 2014 CEA and others.
  * All rights reserved.   This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -7,7 +7,7 @@
  *
  * Contributors:
  *   Christian W. Damus (CEA) - initial API and implementation
- *   Christian W. Damus (CEA) - 409396, 403365, 300957, 405061, 401682, 176998, 180744, 403374
+ *   Christian W. Damus (CEA) - 409396, 403365, 300957, 405061, 401682, 176998, 180744, 403374, 420338
  *   Manuel Bork <bork@yatta.de> (Yatta Solutions GmbH) - 421756, 422000
  *   
  */
@@ -52,6 +52,7 @@
 		result.addTest(Bug180744Test.suite());
 		result.addTest(Bug403374Test.suite());
 		result.addTest(Bug416833Test.suite());
+		result.addTest(Bug420338Test.suite());
 
 		return result;
 	}
diff --git a/tests/org.eclipse.uml2.uml.tests/src/org/eclipse/uml2/uml/tests/util/StandaloneSupport.java b/tests/org.eclipse.uml2.uml.tests/src/org/eclipse/uml2/uml/tests/util/StandaloneSupport.java
index bfb6776..765d4c1 100644
--- a/tests/org.eclipse.uml2.uml.tests/src/org/eclipse/uml2/uml/tests/util/StandaloneSupport.java
+++ b/tests/org.eclipse.uml2.uml.tests/src/org/eclipse/uml2/uml/tests/util/StandaloneSupport.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 CEA and others.
+ * Copyright (c) 2013, 2014 CEA and others.
  * All rights reserved.   This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -7,7 +7,7 @@
  *
  * Contributors:
  *   Christian W. Damus (CEA) - initial API and implementation
- *   Christian W. Damus (CEA) - 414572, 401682
+ *   Christian W. Damus (CEA) - 414572, 401682, 420338
  *
  */
 package org.eclipse.uml2.uml.tests.util;
@@ -20,6 +20,7 @@
 
 import org.eclipse.emf.ecore.plugin.EcorePlugin;
 import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
 import org.eclipse.uml2.uml.resources.util.UMLResourcesUtil;
 
 /**
@@ -52,6 +53,12 @@
 		}
 
 		UMLResourcesUtil.initLocalRegistries(rset);
+
+		if (rset != null) {
+			rset.getResourceFactoryRegistry().getExtensionToFactoryMap()
+				.put("ecore", new EcoreResourceFactoryImpl()); //$NON-NLS-1$
+		}
+
 		return rset;
 	}