[528762] Customizing binary serialization for UML models.
diff --git a/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/resource/UMLResourceImpl.java b/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/resource/UMLResourceImpl.java
index 6a13291..a87fb16 100644
--- a/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/resource/UMLResourceImpl.java
+++ b/plugins/org.eclipse.uml2.uml/src/org/eclipse/uml2/uml/internal/resource/UMLResourceImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011 IBM Corporation, CEA, and others.
+ * Copyright (c) 2005, 2018 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,16 +8,44 @@
  * Contributors:
  *   IBM - initial API and implementation
  *   Kenn Hussey (CEA) - 327039
+ *   Kenn Hussey - 528762
  *
- * $Id: UMLResourceImpl.java,v 1.4 2006/12/14 15:49:34 khussey Exp $
  */
 package org.eclipse.uml2.uml.internal.resource;
 
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.lang.reflect.InvocationTargetException;
+
+import java.util.Map;
+
+import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.NotificationChain;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.TreeIterator;
 import org.eclipse.emf.common.util.URI;
 
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl.BinaryIO.Version;
+import org.eclipse.emf.ecore.EAnnotation;
+import org.eclipse.emf.ecore.EAttribute;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EGenericType;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EOperation;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.InternalEObject;
+import org.eclipse.emf.ecore.resource.impl.BinaryResourceImpl.EObjectOutputStream;
+
 import org.eclipse.emf.ecore.xmi.XMLLoad;
 import org.eclipse.emf.ecore.xmi.XMLSave;
 import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
+import org.eclipse.uml2.uml.UMLPackage;
 import org.eclipse.uml2.uml.resource.UMLResource;
 
 /**
@@ -31,6 +59,443 @@
 		extends XMIResourceImpl
 		implements UMLResource {
 
+	protected static abstract class EStructuralFeatureWrapper
+			implements EStructuralFeature.Internal {
+
+		protected EStructuralFeature.Internal eStructuralFeature;
+
+		protected EStructuralFeatureWrapper(
+				EStructuralFeature.Internal eStructuralFeature) {
+			this.eStructuralFeature = eStructuralFeature;
+		}
+
+		public boolean isTransient() {
+			return eStructuralFeature.isTransient();
+		}
+
+		public void setTransient(boolean value) {
+			eStructuralFeature.setTransient(value);
+		}
+
+		public boolean isVolatile() {
+			return eStructuralFeature.isVolatile();
+		}
+
+		public void setVolatile(boolean value) {
+			eStructuralFeature.setVolatile(value);
+		}
+
+		public boolean isChangeable() {
+			return eStructuralFeature.isChangeable();
+		}
+
+		public void setChangeable(boolean value) {
+			eStructuralFeature.setChangeable(value);
+		}
+
+		public String getDefaultValueLiteral() {
+			return eStructuralFeature.getDefaultValueLiteral();
+		}
+
+		public void setDefaultValueLiteral(String value) {
+			eStructuralFeature.setDefaultValueLiteral(value);
+		}
+
+		public Object getDefaultValue() {
+			return eStructuralFeature.getDefaultValue();
+		}
+
+		public void setDefaultValue(Object value) {
+			eStructuralFeature.setDefaultValue(value);
+		}
+
+		public boolean isUnsettable() {
+			return eStructuralFeature.isUnsettable();
+		}
+
+		public void setUnsettable(boolean value) {
+			eStructuralFeature.setUnsettable(value);
+		}
+
+		public boolean isDerived() {
+			return eStructuralFeature.isDerived();
+		}
+
+		public void setDerived(boolean value) {
+			eStructuralFeature.setDerived(value);
+		}
+
+		public EClass getEContainingClass() {
+			return eStructuralFeature.getEContainingClass();
+		}
+
+		public int getFeatureID() {
+			return eStructuralFeature.getFeatureID();
+		}
+
+		public Class<?> getContainerClass() {
+			return eStructuralFeature.getContainerClass();
+		}
+
+		public boolean isOrdered() {
+			return eStructuralFeature.isOrdered();
+		}
+
+		public void setOrdered(boolean value) {
+			eStructuralFeature.setOrdered(value);
+		}
+
+		public boolean isUnique() {
+			return eStructuralFeature.isUnique();
+		}
+
+		public void setUnique(boolean value) {
+			eStructuralFeature.setUnique(value);
+		}
+
+		public int getLowerBound() {
+			return eStructuralFeature.getLowerBound();
+		}
+
+		public void setLowerBound(int value) {
+			eStructuralFeature.setLowerBound(value);
+		}
+
+		public int getUpperBound() {
+			return eStructuralFeature.getUpperBound();
+		}
+
+		public void setUpperBound(int value) {
+			eStructuralFeature.setUpperBound(value);
+		}
+
+		public boolean isMany() {
+			return eStructuralFeature.isMany();
+		}
+
+		public boolean isRequired() {
+			return eStructuralFeature.isRequired();
+		}
+
+		public EClassifier getEType() {
+			return eStructuralFeature.getEType();
+		}
+
+		public void setEType(EClassifier value) {
+			eStructuralFeature.setEType(value);
+		}
+
+		public EGenericType getEGenericType() {
+			return eStructuralFeature.getEGenericType();
+		}
+
+		public void setEGenericType(EGenericType value) {
+			eStructuralFeature.setEGenericType(value);
+		}
+
+		public String getName() {
+			return eStructuralFeature.getName();
+		}
+
+		public void setName(String value) {
+			eStructuralFeature.setName(value);
+		}
+
+		public EList<EAnnotation> getEAnnotations() {
+			return eStructuralFeature.getEAnnotations();
+		}
+
+		public EAnnotation getEAnnotation(String source) {
+			return eStructuralFeature.getEAnnotation(source);
+		}
+
+		public EClass eClass() {
+			return eStructuralFeature.eClass();
+		}
+
+		public Resource eResource() {
+			return eStructuralFeature.eResource();
+		}
+
+		public EObject eContainer() {
+			return eStructuralFeature.eContainer();
+		}
+
+		public EStructuralFeature eContainingFeature() {
+			return eStructuralFeature.eContainingFeature();
+		}
+
+		public org.eclipse.emf.ecore.EReference eContainmentFeature() {
+			return eStructuralFeature.eContainmentFeature();
+		}
+
+		public EList<EObject> eContents() {
+			return eStructuralFeature.eContents();
+		}
+
+		public TreeIterator<EObject> eAllContents() {
+			return eStructuralFeature.eAllContents();
+		}
+
+		public boolean eIsProxy() {
+			return eStructuralFeature.eIsProxy();
+		}
+
+		public EList<EObject> eCrossReferences() {
+			return eStructuralFeature.eCrossReferences();
+		}
+
+		public Object eGet(EStructuralFeature feature) {
+			return eStructuralFeature.eGet(feature);
+		}
+
+		public Object eGet(EStructuralFeature feature, boolean resolve) {
+			return eStructuralFeature.eGet(feature, resolve);
+		}
+
+		public void eSet(EStructuralFeature feature, Object newValue) {
+			eStructuralFeature.eSet(feature, newValue);
+		}
+
+		public boolean eIsSet(EStructuralFeature feature) {
+			return eStructuralFeature.eIsSet(feature);
+		}
+
+		public void eUnset(EStructuralFeature feature) {
+			eStructuralFeature.eUnset(feature);
+		}
+
+		public Object eInvoke(EOperation operation, EList<?> arguments)
+				throws InvocationTargetException {
+			return eStructuralFeature.eInvoke(operation, arguments);
+		}
+
+		public EList<Adapter> eAdapters() {
+			return eStructuralFeature.eAdapters();
+		}
+
+		public boolean eDeliver() {
+			return eStructuralFeature.eDeliver();
+		}
+
+		public void eSetDeliver(boolean deliver) {
+			eStructuralFeature.eSetDeliver(deliver);
+		}
+
+		public void eNotify(Notification notification) {
+			eStructuralFeature.eNotify(notification);
+		}
+
+		public boolean eNotificationRequired() {
+			return eStructuralFeature.eNotificationRequired();
+		}
+
+		public String eURIFragmentSegment(EStructuralFeature eFeature,
+				EObject eObject) {
+			return eStructuralFeature.eURIFragmentSegment(eFeature, eObject);
+		}
+
+		public EObject eObjectForURIFragmentSegment(String uriFragmentSegment) {
+			return eStructuralFeature
+				.eObjectForURIFragmentSegment(uriFragmentSegment);
+		}
+
+		public void eSetClass(EClass eClass) {
+			eStructuralFeature.eSetClass(eClass);
+		}
+
+		public Setting eSetting(EStructuralFeature feature) {
+			return eStructuralFeature.eSetting(feature);
+		}
+
+		public int eBaseStructuralFeatureID(int derivedFeatureID,
+				Class<?> baseClass) {
+			return eStructuralFeature.eBaseStructuralFeatureID(derivedFeatureID,
+				baseClass);
+		}
+
+		public int eContainerFeatureID() {
+			return eStructuralFeature.eContainerFeatureID();
+		}
+
+		public int eDerivedStructuralFeatureID(int baseFeatureID,
+				Class<?> baseClass) {
+			return eStructuralFeature.eDerivedStructuralFeatureID(baseFeatureID,
+				baseClass);
+		}
+
+		public int eDerivedOperationID(int baseOperationID,
+				Class<?> baseClass) {
+			return eStructuralFeature.eDerivedOperationID(baseOperationID,
+				baseClass);
+		}
+
+		public NotificationChain eSetResource(
+				org.eclipse.emf.ecore.resource.Resource.Internal resource,
+				NotificationChain notifications) {
+			return eStructuralFeature.eSetResource(resource, notifications);
+		}
+
+		public NotificationChain eInverseAdd(InternalEObject otherEnd,
+				int featureID, Class<?> baseClass,
+				NotificationChain notifications) {
+			return eStructuralFeature.eInverseAdd(otherEnd, featureID,
+				baseClass, notifications);
+		}
+
+		public NotificationChain eInverseRemove(InternalEObject otherEnd,
+				int featureID, Class<?> baseClass,
+				NotificationChain notifications) {
+			return eStructuralFeature.eInverseRemove(otherEnd, featureID,
+				baseClass, notifications);
+		}
+
+		public NotificationChain eBasicSetContainer(
+				InternalEObject newContainer, int newContainerFeatureID,
+				NotificationChain notifications) {
+			return eStructuralFeature.eBasicSetContainer(newContainer,
+				newContainerFeatureID, notifications);
+		}
+
+		public NotificationChain eBasicRemoveFromContainer(
+				NotificationChain notifications) {
+			return eStructuralFeature.eBasicRemoveFromContainer(notifications);
+		}
+
+		public URI eProxyURI() {
+			return eStructuralFeature.eProxyURI();
+		}
+
+		public void eSetProxyURI(URI uri) {
+			eStructuralFeature.eSetProxyURI(uri);
+		}
+
+		public EObject eResolveProxy(InternalEObject proxy) {
+			return eStructuralFeature.eResolveProxy(proxy);
+		}
+
+		public InternalEObject eInternalContainer() {
+			return eStructuralFeature.eInternalContainer();
+		}
+
+		public org.eclipse.emf.ecore.resource.Resource.Internal eInternalResource() {
+			return eStructuralFeature.eInternalResource();
+		}
+
+		public org.eclipse.emf.ecore.resource.Resource.Internal eDirectResource() {
+			return eStructuralFeature.eDirectResource();
+		}
+
+		public EStore eStore() {
+			return eStructuralFeature.eStore();
+		}
+
+		public void eSetStore(EStore store) {
+			eStructuralFeature.eSetStore(store);
+		}
+
+		public Object eGet(EStructuralFeature eFeature, boolean resolve,
+				boolean coreType) {
+			return eStructuralFeature.eGet(eFeature, resolve, coreType);
+		}
+
+		public Object eGet(int featureID, boolean resolve, boolean coreType) {
+			return eStructuralFeature.eGet(featureID, resolve, coreType);
+		}
+
+		public void eSet(int featureID, Object newValue) {
+			eStructuralFeature.eSet(featureID, newValue);
+		}
+
+		public void eUnset(int featureID) {
+			eStructuralFeature.eUnset(featureID);
+		}
+
+		public boolean eIsSet(int featureID) {
+			return eStructuralFeature.eIsSet(featureID);
+		}
+
+		public Object eInvoke(int operationID, EList<?> arguments)
+				throws InvocationTargetException {
+			return eStructuralFeature.eInvoke(operationID, arguments);
+		}
+
+		public SettingDelegate getSettingDelegate() {
+			return eStructuralFeature.getSettingDelegate();
+		}
+
+		public void setSettingDelegate(SettingDelegate settingDelegate) {
+			eStructuralFeature.setSettingDelegate(settingDelegate);
+		}
+
+		public boolean isFeatureMap() {
+			return eStructuralFeature.isFeatureMap();
+		}
+
+		public org.eclipse.emf.ecore.util.FeatureMap.Entry.Internal getFeatureMapEntryPrototype() {
+			return eStructuralFeature.getFeatureMapEntryPrototype();
+		}
+
+		public void setFeatureMapEntryPrototype(
+				org.eclipse.emf.ecore.util.FeatureMap.Entry.Internal prototype) {
+			eStructuralFeature.setFeatureMapEntryPrototype(prototype);
+		}
+
+		public boolean isID() {
+			return eStructuralFeature.isID();
+		}
+
+		public boolean isResolveProxies() {
+			return eStructuralFeature.isResolveProxies();
+		}
+
+		public boolean isContainer() {
+			return eStructuralFeature.isContainer();
+		}
+
+		public boolean isContainment() {
+			return eStructuralFeature.isContainment();
+		}
+
+		public org.eclipse.emf.ecore.EReference getEOpposite() {
+			return eStructuralFeature.getEOpposite();
+		}
+
+	}
+
+	protected static class EReferenceWrapper
+			extends EStructuralFeatureWrapper
+			implements EReference {
+
+		protected EReferenceWrapper(EReference eReference) {
+			super((EStructuralFeature.Internal) eReference);
+		}
+
+		protected EReference getEReference() {
+			return (EReference) eStructuralFeature;
+		}
+
+		public void setContainment(boolean value) {
+			getEReference().setContainment(value);
+		}
+
+		public void setResolveProxies(boolean value) {
+			getEReference().setResolveProxies(value);
+		}
+
+		public void setEOpposite(EReference value) {
+			getEReference().setEOpposite(value);
+		}
+
+		public EClass getEReferenceType() {
+			return getEReference().getEReferenceType();
+		}
+
+		public EList<EAttribute> getEKeys() {
+			return getEReference().getEKeys();
+		}
+	}
+	
 	/**
 	 * Creates an instance of the resource.
 	 * <!-- begin-user-doc -->
@@ -62,4 +527,40 @@
 		return true;
 	}
 
+	@Override
+	protected EObjectOutputStream createEObjectOutputStream(
+			OutputStream outputStream, Map<?, ?> options, Version version,
+			final URIHandler uriHandler)
+			throws IOException {
+		return new EObjectOutputStream(outputStream, options, version) {
+
+			@Override
+			protected URI deresolve(URI uri) {
+				return uriHandler == null
+					? super.deresolve(uri)
+					: uriHandler.deresolve(uri);
+			}
+
+			@Override
+			protected EStructuralFeatureData createEStructuralFeatureData(
+					EStructuralFeature.Internal eStructuralFeature) {
+
+				if (eStructuralFeature == UMLPackage.Literals.ACTIVITY__GROUP
+					|| eStructuralFeature == UMLPackage.Literals.ACTIVITY__NODE) {
+
+					eStructuralFeature = new EReferenceWrapper(
+						(EReference) eStructuralFeature) {
+
+						public boolean isTransient() {
+							return false;
+						}
+					};
+				}
+
+				return super.createEStructuralFeatureData(eStructuralFeature);
+			}
+
+		};
+	}
+
 } //UMLResourceImpl
diff --git a/tests/org.eclipse.uml2.uml.tests/src/org/eclipse/uml2/uml/bug/tests/Bug528762Test.java b/tests/org.eclipse.uml2.uml.tests/src/org/eclipse/uml2/uml/bug/tests/Bug528762Test.java
new file mode 100644
index 0000000..5603616
--- /dev/null
+++ b/tests/org.eclipse.uml2.uml.tests/src/org/eclipse/uml2/uml/bug/tests/Bug528762Test.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2018 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:
+ *   Sebastien Revol (CEA) - initial API and implementation
+ *   Kenn Hussey - 528762
+ *
+ */
+package org.eclipse.uml2.uml.bug.tests;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.emf.common.util.URI;
+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.xmi.XMIResource;
+import org.eclipse.uml2.uml.Activity;
+import org.eclipse.uml2.uml.Model;
+import org.eclipse.uml2.uml.UMLFactory;
+import org.eclipse.uml2.uml.UMLPackage;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class Bug528762Test
+		extends TestCase {
+
+	public Bug528762Test() {
+		super();
+	}
+
+	public static Test suite() {
+		return new TestSuite(Bug512520Test.class, "Bug 528762 tests"); //$NON-NLS-1$
+	}
+
+
+	public void testBinarySerialization() {
+		Model model = UMLFactory.eINSTANCE.createModel();
+		model.setName("modelName"); //$NON-NLS-1$
+		String activityName = "activity"; //$NON-NLS-1$
+
+		Activity activity = (Activity) model.createOwnedType(activityName,
+			UMLPackage.eINSTANCE.getActivity());
+
+		for (int i = 0; i < 10; i++) {
+			activity.createOwnedNode("action" + i, //$NON-NLS-1$
+				UMLPackage.eINSTANCE.getOpaqueAction());
+		}
+		assertEquals(10, activity.getOwnedNodes().size());
+		assertEquals(10, activity.getNodes().size());
+
+		try {
+			URI tmpURI = URI.createFileURI("Bug528762.uml"); //$NON-NLS-1$
+			ResourceSet resSet = new ResourceSetImpl();
+			Resource outputResource = resSet.createResource(tmpURI);
+			outputResource.getContents().add(model);
+
+			Map<Object, Object> options = new HashMap<Object, Object>();
+
+			options.put(XMIResource.OPTION_BINARY, Boolean.TRUE);
+			outputResource.save(options);
+
+			resSet = new ResourceSetImpl();
+
+			outputResource.unload();
+			outputResource.eAdapters().clear();
+
+			resSet.getResources().clear();
+			resSet.eAdapters().clear();
+
+			outputResource = resSet.createResource(tmpURI);
+
+			outputResource.unload();
+			outputResource.eAdapters().clear();
+
+			resSet.getResources().clear();
+			resSet.eAdapters().clear();
+
+			outputResource.unload();
+
+			outputResource.load(options);
+
+			model = (Model) outputResource.getContents().get(0);
+			activity = (Activity) model.getPackagedElement(activityName, false,
+				UMLPackage.eINSTANCE.getActivity(), false);
+			assertEquals(10, activity.getOwnedNodes().size());
+			assertEquals(10, activity.getNodes().size());
+
+		} catch (IOException ioe) {
+			ioe.printStackTrace();
+			fail();
+		}
+	}
+
+}
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 2a939e1..ce507c2 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, 2017 CEA, Christian W. Damus, and others.
+ * Copyright (c) 2013, 2018 CEA, Christian W. Damus, 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
@@ -11,7 +11,7 @@
  *   Manuel Bork <bork@yatta.de> (Yatta Solutions GmbH) - 421756, 422000
  *   Kenn Hussey (CEA) - 424895, 511674, 512520
  *   Christian W. Damus - 444588, 497359, 501740
- *   Kenn Hussey - 526679
+ *   Kenn Hussey - 526679, 528762
  *   
  */
 package org.eclipse.uml2.uml.bug.tests;
@@ -67,6 +67,7 @@
 		result.addTest(Bug501740Test.suite());
 		result.addTest(Bug511674Test.suite());
 		result.addTest(Bug512520Test.suite());
+		result.addTest(Bug528762Test.suite());
 		
 		// keep this one at the end because it runs long
 		result.addTest(Bug332057Test.suite());