[418716] Add OCLSettingDelegate.Changeable
diff --git a/plugins/org.eclipse.ocl.ecore/src/org/eclipse/ocl/ecore/delegate/OCLSettingDelegate.java b/plugins/org.eclipse.ocl.ecore/src/org/eclipse/ocl/ecore/delegate/OCLSettingDelegate.java
index 58132ad..fd208cf 100644
--- a/plugins/org.eclipse.ocl.ecore/src/org/eclipse/ocl/ecore/delegate/OCLSettingDelegate.java
+++ b/plugins/org.eclipse.ocl.ecore/src/org/eclipse/ocl/ecore/delegate/OCLSettingDelegate.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2010, 2012 Willink Transformations and others.
+ * Copyright (c) 2010, 2015 Willink Transformations 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
@@ -10,6 +10,9 @@
  *******************************************************************************/
 package org.eclipse.ocl.ecore.delegate;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import org.eclipse.emf.ecore.EStructuralFeature;
 import org.eclipse.emf.ecore.InternalEObject;
 import org.eclipse.emf.ecore.util.BasicSettingDelegate;
@@ -26,6 +29,51 @@
  */
 public class OCLSettingDelegate extends BasicSettingDelegate.Stateless
 {
+	/**
+	 * An implementation of a setting delegate that computes OCL derived features
+	 * and caches explicitly changed values.
+	 * 
+	 * @since 3.5
+	 */
+	public static class Changeable extends OCLSettingDelegate
+	{
+		private Map<InternalEObject, Object> valueMap = null;
+
+		public Changeable(OCLDelegateDomain delegateDomain, EStructuralFeature structuralFeature) {
+			super(delegateDomain, structuralFeature);
+		}
+
+		@Override
+		protected Object get(InternalEObject owner, boolean resolve, boolean coreType) {
+			if ((valueMap != null) && valueMap.containsKey(owner)) {
+				return valueMap.get(owner);
+			}
+			return super.get(owner, resolve, coreType);
+		}
+
+		@Override
+		protected boolean isSet(InternalEObject owner) {
+			return (valueMap != null) && valueMap.containsKey(owner);
+		}
+
+		@Override
+		protected void set(InternalEObject owner, Object newValue) {
+			if (owner != null) {
+				if (valueMap == null) {
+					valueMap = new HashMap<InternalEObject, Object>();
+				}
+				valueMap.put(owner, newValue);
+			}
+		}
+
+		@Override
+		protected void unset(InternalEObject owner) {
+			if (valueMap != null) {
+				valueMap.remove(owner);
+			}
+		}
+	}
+	
 	protected final OCLDelegateDomain delegateDomain;
 	private OCLExpression derivation;
 	private ValueConverter converter;
diff --git a/plugins/org.eclipse.ocl.ecore/src/org/eclipse/ocl/ecore/delegate/OCLSettingDelegateFactory.java b/plugins/org.eclipse.ocl.ecore/src/org/eclipse/ocl/ecore/delegate/OCLSettingDelegateFactory.java
index 7e03588..8b16069 100644
--- a/plugins/org.eclipse.ocl.ecore/src/org/eclipse/ocl/ecore/delegate/OCLSettingDelegateFactory.java
+++ b/plugins/org.eclipse.ocl.ecore/src/org/eclipse/ocl/ecore/delegate/OCLSettingDelegateFactory.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2010, 2014 Willink Transformations and others.
+ * Copyright (c) 2010, 2015 Willink Transformations 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
@@ -54,7 +54,12 @@
 
 	public EStructuralFeature.Internal.SettingDelegate createSettingDelegate(EStructuralFeature structuralFeature) {
 		EPackage ePackage = structuralFeature.getEContainingClass().getEPackage();
-		return new OCLSettingDelegate(getDelegateDomain(ePackage), structuralFeature);
+		if (structuralFeature.isChangeable() && !structuralFeature.isVolatile()) {
+			return new OCLSettingDelegate.Changeable(getDelegateDomain(ePackage), structuralFeature);
+		}
+		else {
+			return new OCLSettingDelegate(getDelegateDomain(ePackage), structuralFeature);
+		}
 	}
 	
 	/**
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/delegate/OCLSettingDelegate.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/delegate/OCLSettingDelegate.java
index acf7f35..7f18756 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/delegate/OCLSettingDelegate.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/delegate/OCLSettingDelegate.java
@@ -10,6 +10,9 @@
  *******************************************************************************/
 package org.eclipse.ocl.pivot.internal.delegate;
 
+import java.util.HashMap;
+import java.util.Map;
+
 import org.eclipse.emf.ecore.EStructuralFeature;
 import org.eclipse.emf.ecore.InternalEObject;
 import org.eclipse.emf.ecore.util.BasicSettingDelegate;
@@ -30,6 +33,51 @@
  */
 public class OCLSettingDelegate extends BasicSettingDelegate.Stateless
 {
+	/**
+	 * An implementation of a setting delegate that computes OCL derived features
+	 * and caches explicitly changed values.
+	 * 
+	 * @since 3.5
+	 */
+	public static class Changeable extends OCLSettingDelegate
+	{
+		private Map<InternalEObject, Object> valueMap = null;
+
+		public Changeable(@NonNull OCLDelegateDomain delegateDomain, @NonNull EStructuralFeature structuralFeature) {
+			super(delegateDomain, structuralFeature);
+		}
+
+		@Override
+		protected Object get(InternalEObject owner, boolean resolve, boolean coreType) {
+			if ((valueMap != null) && valueMap.containsKey(owner)) {
+				return valueMap.get(owner);
+			}
+			return super.get(owner, resolve, coreType);
+		}
+
+		@Override
+		protected boolean isSet(InternalEObject owner) {
+			return (valueMap != null) && valueMap.containsKey(owner);
+		}
+
+		@Override
+		protected void set(InternalEObject owner, Object newValue) {
+			if (owner != null) {
+				if (valueMap == null) {
+					valueMap = new HashMap<InternalEObject, Object>();
+				}
+				valueMap.put(owner, newValue);
+			}
+		}
+
+		@Override
+		protected void unset(InternalEObject owner) {
+			if (valueMap != null) {
+				valueMap.remove(owner);
+			}
+		}
+	}
+	
 	protected final @NonNull OCLDelegateDomain delegateDomain;
 	private Property property;
 	private ExpressionInOCL query;
diff --git a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/delegate/OCLSettingDelegateFactory.java b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/delegate/OCLSettingDelegateFactory.java
index 6784c9a..c4ce6b5 100644
--- a/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/delegate/OCLSettingDelegateFactory.java
+++ b/plugins/org.eclipse.ocl.pivot/src/org/eclipse/ocl/pivot/internal/delegate/OCLSettingDelegateFactory.java
@@ -38,7 +38,12 @@
 		if (delegateDomain == null) {
 			return null;
 		}
-		return new OCLSettingDelegate(delegateDomain, structuralFeature);
+		if (structuralFeature.isChangeable() && !structuralFeature.isVolatile()) {
+			return new OCLSettingDelegate.Changeable(delegateDomain, structuralFeature);
+		}
+		else {
+			return new OCLSettingDelegate(delegateDomain, structuralFeature);
+		}
 	}
 	
 	/**