blob: 3584b771acc744ed4e6423de64b16d81c6f75b5a [file] [log] [blame]
/**
* This file was copied and re-packaged automatically by
* org.eclipse.ocl.examples.build.GenerateAutoCSModels.mwe2
* from
* ..\..\..\org.eclipse.qvtd\plugins\org.eclipse.qvtd.runtime\src\org\eclipse\qvtd\runtime\internal\evaluation\IncrementalObjectManager.java
*
* Do not edit this file.
*/
/*******************************************************************************
* Copyright (c) 2013, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* E.D.Willink - Initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.pivot.internal.evaluation.tx;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.oclstdlib.OCLstdlibPackage;
import org.eclipse.ocl.pivot.evaluation.tx.AbstractObjectManager;
import org.eclipse.ocl.pivot.evaluation.tx.AbstractSlotState;
import org.eclipse.ocl.pivot.evaluation.tx.AbstractTransformer;
import org.eclipse.ocl.pivot.evaluation.tx.Invocation;
import org.eclipse.ocl.pivot.evaluation.tx.InvocationFailedException;
import org.eclipse.ocl.pivot.evaluation.tx.ObjectManager;
import org.eclipse.ocl.pivot.evaluation.tx.SlotState;
/**
* @since 1.1
*/
public class IncrementalObjectManager extends AbstractObjectManager
{
/**
* Simple SlotState describing a DataType element or 1:1 Object navigation.
*/
public static abstract class BasicSlotState extends AbstractSlotState.Incremental
{
public enum SlotMode {
ASSIGNABLE, // No assignment has been performed, object reads are blocked (collections reads may be unblocked)
ASSIGNED // Last assignment has been performed, reads are unblocked
}
protected final @NonNull Object eObject;
protected final @NonNull EStructuralFeature eFeature;
private @Nullable Object value = null;
protected @NonNull SlotMode mode;
private @Nullable Object blockedInvocations = null;
public BasicSlotState(@NonNull Object eObject, @NonNull EStructuralFeature eFeature) {
mode = SlotMode.ASSIGNABLE;
this.eObject = eObject;
this.eFeature = eFeature;
}
public BasicSlotState(@NonNull Object eObject, @NonNull EStructuralFeature eFeature, @Nullable Object ecoreValue) {
mode = SlotMode.ASSIGNED;
this.eObject = eObject;
this.eFeature = eFeature;
this.value = ecoreValue;
}
public synchronized void assigned(@NonNull IncrementalObjectManager objectManager, @NonNull Object eObject, @NonNull EStructuralFeature eFeature, @Nullable Object ecoreValue) {
switch (mode) {
case ASSIGNABLE:
mode = SlotMode.ASSIGNED;
unblock(objectManager);
break;
case ASSIGNED:
System.out.println("Re-assignment of " + eFeature.getEContainingClass().getName() + "::" + eFeature.getName() + " for " + eObject + " with " + ecoreValue);
break;
}
this.value = ecoreValue;
}
@Override
public synchronized void block(@NonNull Invocation invocation) {
final Object blockedInvocations2 = blockedInvocations;
if (blockedInvocations2 == null) {
blockedInvocations = invocation;
}
else if (blockedInvocations2 instanceof Invocation) {
List<Invocation> blockedInvocationList = new ArrayList<Invocation>();
blockedInvocationList.add((Invocation) blockedInvocations2);
blockedInvocationList.add(invocation);
blockedInvocations = blockedInvocationList;
}
else {
@SuppressWarnings("unchecked")
List<Invocation> blockedInvocationList = (List<Invocation>)blockedInvocations2;
blockedInvocationList.add(invocation);
}
}
@Override
public @NonNull EStructuralFeature getEFeature() {
return eFeature;
}
@Override
public SlotState.@NonNull Incremental getPrimarySlotState() {
return this;
}
@Override
public @Nullable Object getValue() {
return value;
}
@Override
public synchronized void getting( @NonNull Object eObject, @NonNull EStructuralFeature eFeature) {
switch (mode) {
case ASSIGNABLE:
throw new InvocationFailedException(this);
case ASSIGNED:
break;
}
}
protected boolean isAssigned() {
return mode == SlotMode.ASSIGNED;
}
@Override
public String toString() {
return getClass().getSimpleName() + "@" + Integer.toHexString(System.identityHashCode(this)) + "[" + eFeature.getEContainingClass().getName() + "::" + eFeature.getName() + " for " + eObject + "]";
}
protected synchronized void unblock(@NonNull ObjectManager objectManager) {
final Object blockedInvocations2 = blockedInvocations;
if (blockedInvocations2 instanceof Invocation) {
objectManager.unblock((Invocation) blockedInvocations2);
}
else if (blockedInvocations2 != null) {
@SuppressWarnings("unchecked")
List<Invocation> blockedInvocationList = (List<Invocation>)blockedInvocations2;
for (@SuppressWarnings("null")@NonNull Invocation invocation : blockedInvocationList) {
objectManager.unblock(invocation);
}
}
blockedInvocations = null;
}
}
/**
* SlotState describing the contained element side of a 1:N Object navigation.
* A single OneToManyContainedSlotState is shared by each of the possible containing features and also the
* generic OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER corresponding to eContainer().
* The eGet() must therefore check not only that the proprty is assigned but also that it is
* assigned to the containing feature of interest.
* <br>
* Lifecycle (read first, write later):
* Create due to
* - get of an aggregator => ASSIGNABLE, blocked
* Unblock
* - assign of possibly null aggregator for the element, ASSIGNABLE, blocked => ASSIGNED, not blocked
* - non-null aggregator is notified to unblock
* Thereafter
* - get of aggregator ASSIGNED => ASSIGNED
* <br>
* Lifecycle (write first):
* Create due to
* - assign of a possibly null aggregator => ASSIGNED, unblocked
* - non-null aggregator is notified to unblock
* Thereafter
* - get of aggregator ASSIGNED => ASSIGNED
*
private static class ContainedSlotState extends SlotState
{
public static @NonNull SlotState create(@NonNull ObjectManager objectManager,
@NonNull EObject eObject, @NonNull EReference eFeature, @Nullable EReference eOppositeFeature, @Nullable EObject eContainer) {
if (eOppositeFeature == null) {
eOppositeFeature = OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER;
assert eOppositeFeature != null;
}
if (eContainer != null) {
ContainerSlotState aggregatorSlotState = (ContainerSlotState) objectManager.getSlotState(eContainer, eOppositeFeature);
aggregatorSlotState.assignedElement(objectManager, eContainer, eOppositeFeature, eObject);
}
return new ContainedSlotState(eObject, eFeature, eContainer);
}
public ContainedSlotState(@NonNull EObject eObject, @NonNull EReference eFeature) {
super(eObject, eFeature);
assert !eFeature.isMany();
if (eFeature != OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER) { // FIXME ensure oclContainer() composes
assert eFeature.isContainment();
assert eFeature.getEOpposite() != null;
}
// assert eFeature.getEOpposite().isMany();
}
private ContainedSlotState(@NonNull EObject eObject, @NonNull EReference eFeature, @Nullable EObject eContainer) {
super(eObject, eFeature, eContainer);
assert !eFeature.isMany();
if (eFeature != OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER) { // FIXME ensure oclContainer() composes
assert eFeature.isContainment();
}
// assert eFeature.getEOpposite().isMany();
assert eObject.eContainer() == eContainer;
}
@Override
public synchronized void assigned(@NonNull ObjectManager objectManager, @NonNull EObject eObject, @NonNull EStructuralFeature eFeature, @Nullable Object ecoreValue) {
if (!isAssigned() && (ecoreValue != null)) {
EObject eOpposite = (EObject) ecoreValue;
EReference eOppositeReference = ((EReference)eFeature).getEOpposite();
assert eOppositeReference != null;
ContainerSlotState aggregatorSlotState = (ContainerSlotState) objectManager.getSlotState(eOpposite, eOppositeReference);
aggregatorSlotState.assignedElement(objectManager, eOpposite, eOppositeReference, eObject);
}
super.assigned(objectManager, eObject, eFeature, ecoreValue);
}
@Override
@SuppressWarnings("unchecked")
public synchronized @Nullable <G> G get(@NonNull ObjectManager objectManager, @NonNull EObject eObject, @NonNull EStructuralFeature eFeature) {
switch (mode) {
case ASSIGNABLE:
throw new InvocationFailedException(this);
case ASSIGNED:
break;
}
if (eFeature != OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER) {
EStructuralFeature eContainingFeature = eObject.eContainingFeature();
if (eContainingFeature != eFeature) {
return null;
}
}
return (G) eObject.eContainer();
}
} */
/**
* SlotState describing the container side of a 1:N Object navigation.
* <br>
* Lifecycle:
* Create due to
* - get of all elements => ASSIGNABLE, blocked
* NO: - get of a container => ASSIGNABLE, blocked
* Create due to
* - assign of all elements => ASSIGNABLE => ASSIGNED, not blocked
* - assign of a first element to the container => ASSIGNABLE, not blocked
* Update due to
* - assign of a further element to the container => ASSIGNABLE => ASSIGNABLE
* Unblock due to
* - get of a container ASSIGNABLE => ASSIGNED
* - get of all elements ASSIGNABLE => ASSIGNED
* Thereafter
* - get of a container ASSIGNED => ASSIGNED
* - get of all elements ASSIGNED => ASSIGNED
* <br>
* Lifecycle 2: read first
* Create due to
* - get of elements => ASSIGNABLE, blocked
* Unblock due to
* - assign of an element to the container => ASSIGNABLE => ASSIGNED, not blocked
* Thereafter
* - get of either end ASSIGNED => ASSIGNED
* - (assign of either end is an ignored error)
*
private static class ContainerSlotState extends SlotState
{
public static @NonNull SlotState create(@NonNull ObjectManager objectManager,
@NonNull EObject eObject, @NonNull EReference eFeature, @NonNull EReference eOppositeFeature, @Nullable EObject eContent) {
if (eContent != null) {
ContainedSlotState containedSlotState = (ContainedSlotState) objectManager.getSlotState(eContent, eOppositeFeature);
containedSlotState.assigned(objectManager, eContent, eOppositeFeature, eObject);
}
return new ContainerSlotState(eObject, eFeature, eContent);
}
public ContainerSlotState(@NonNull EObject eContainer, @NonNull EReference eFeature) {
super(eContainer, eFeature);
assert eFeature.isContainer();
// assert eFeature.isMany();
// assert eFeature.getEOpposite() != null;
// assert eFeature.getEOpposite().isMany();
}
public ContainerSlotState(@NonNull EObject eContainer, @NonNull EReference eFeature, @Nullable Object elements) {
super(eContainer, eFeature, elements);
assert eFeature.isContainer();
// assert eFeature.isMany();
// assert eFeature.getEOpposite() != null;
// assert eFeature.getEOpposite().isMany();
assert eContainer.eGet(eFeature) == eContainer;
}
@Override
public synchronized void assigned(@NonNull ObjectManager objectManager, @NonNull EObject eObject, @NonNull EStructuralFeature eFeature, @Nullable Object ecoreValue) {
assert ecoreValue != null;
@SuppressWarnings("unchecked")
List<? extends EObject> ecoreValues = (List<? extends EObject>)ecoreValue;
EReference eOppositeReference = ((EReference)eFeature).getEOpposite();
for (EObject element : ecoreValues) {
if (element != null) {
Map<EStructuralFeature, SlotState> elementObjectState = objectManager.getObjectState(element);
elementObjectState.put(eOppositeReference, this);
}
}
super.assigned(objectManager, eObject, eFeature, ecoreValue);
}
public void assignedElement(@NonNull ObjectManager objectManager,
@NonNull EObject eContainer, @NonNull EReference eReference, EObject eObject) {
super.assigned(objectManager, eContainer, eReference, eObject);
}
@Override
@SuppressWarnings("unchecked")
public synchronized @Nullable <G> G get(@NonNull ObjectManager objectManager, @NonNull EObject eObject, @NonNull EStructuralFeature eFeature) {
switch (mode) {
case ASSIGNABLE:
mode = PropertyMode.ASSIGNED;
unblock(objectManager);
break;
case ASSIGNED:
break;
}
return (G) eObject.eGet(eFeature);
}
} */
/**
* SlotState describing an M:N Object navigation.
*/
class ManyToManySlotState extends BasicSlotState
{
public ManyToManySlotState(@NonNull Object eObject, @NonNull EStructuralFeature eFeature) {
super(eObject, eFeature);
throw new UnsupportedOperationException();
}
@Override
public synchronized void assigned(@NonNull Object eObject, @NonNull EStructuralFeature eFeature, @Nullable Object ecoreValue) {
throw new UnsupportedOperationException();
}
}
/**
* SlotState describing the aggregator side of a 1:N Object navigation.
* <br>
* Lifecycle:
* Create due to
* - get of all elements => ASSIGNABLE, blocked
* NO: - get of an aggregator => ASSIGNABLE, blocked
* Create due to
* - assign of all elements => ASSIGNABLE => ASSIGNED, not blocked
* - assign of a first element to the aggregator => ASSIGNABLE, not blocked
* Update due to
* - assign of a further element to the aggregator => ASSIGNABLE => ASSIGNABLE
* Unblock due to
* - get of an aggregator ASSIGNABLE => ASSIGNED
* - get of all elements ASSIGNABLE => ASSIGNED
* Thereafter
* - get of an aggregator ASSIGNED => ASSIGNED
* - get of all elements ASSIGNED => ASSIGNED
* <br>
* Lifecycle 2: read first
* Create due to
* - get of elements => ASSIGNABLE, blocked
* Unblock due to
* - assign of an element to the aggregator => ASSIGNABLE => ASSIGNED, not blocked
* Thereafter
* - get of either end ASSIGNED => ASSIGNED
* - (assign of either end is an ignored error)
*/
class OneToManyAggregatorSlotState extends BasicSlotState
{
// public static @NonNull SlotState create(@NonNull ObjectManager objectManager,
// EObject eObject, @NonNull EReference eFeature, EReference eOppositeReference, Object ecoreValue) {
// // TODO Auto-generated method stub
// return null;
// }
public OneToManyAggregatorSlotState(@NonNull Object eContainer, @NonNull EStructuralFeature eFeature) {
super(eContainer, eFeature);
assert eFeature.isMany();
// assert eFeature.getEOpposite() != null;
// assert eFeature.getEOpposite().isMany();
}
private OneToManyAggregatorSlotState(@NonNull Object eContainer, @NonNull EStructuralFeature eFeature, @Nullable Object eContents) {
super(eContainer, eFeature, eContents);
assert eFeature.isMany();
// assert eFeature.getEOpposite() != null;
// assert eFeature.getEOpposite().isMany();
assert ((EObject)eContainer).eGet(eFeature).equals(eContents);
}
@Override
public synchronized void assigned(@NonNull Object eObject, @NonNull EStructuralFeature eFeature, @Nullable Object ecoreValue) {
assert ecoreValue != null;
@SuppressWarnings("unchecked")
List<? extends EObject> ecoreValues = (List<? extends EObject>)ecoreValue;
EReference eOppositeReference = ((EReference)eFeature).getEOpposite();
for (EObject element : ecoreValues) {
if (element != null) {
Map<EStructuralFeature, BasicSlotState> elementObjectState = getObjectState(element);
elementObjectState.put(eOppositeReference, this);
}
}
// super.assigned(objectManager, eObject, eFeature, ecoreValue);
assignedElement(eObject, (EReference)eFeature, (EObject)ecoreValue);
}
public void assignedElement(@NonNull Object eContainer, @NonNull EReference eReference, Object eObject) {
// super.assigned(objectManager, eContainer, eReference, eObject);
switch (mode) {
case ASSIGNABLE:
mode = SlotMode.ASSIGNED;
unblock(IncrementalObjectManager.this);
break;
case ASSIGNED:
break;
}
}
@Override
public synchronized void getting(@NonNull Object eObject, @NonNull EStructuralFeature eFeature) {
switch (mode) {
case ASSIGNABLE:
mode = SlotMode.ASSIGNED;
unblock(IncrementalObjectManager.this);
break;
case ASSIGNED:
break;
}
}
}
/**
* SlotState describing the element side of a 1:N Object navigation.
* <br>
* Lifecycle (read first, write later):
* Create due to
* - get of an aggregator => ASSIGNABLE, blocked
* Unblock
* - assign of possibly null aggregator for the element, ASSIGNABLE, blocked => ASSIGNED, not blocked
* - non-null aggregator is notified to unblock
* Thereafter
* - get of aggregator ASSIGNED => ASSIGNED
* <br>
* Lifecycle (write first):
* Create due to
* - assign of a possibly null aggregator => ASSIGNED, unblocked
* - non-null aggregator is notified to unblock
* Thereafter
* - get of aggregator ASSIGNED => ASSIGNED
*/
class OneToManyElementSlotState extends BasicSlotState
{
public OneToManyElementSlotState(@NonNull Object eObject, @NonNull EReference eFeature) {
super(eObject, eFeature);
assert !eFeature.isMany();
if (eFeature == OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER) {
assert eFeature.getEOpposite() == null;
}
else {
assert eFeature.getEOpposite() != null;
assert eFeature.getEOpposite().isMany();
}
}
public OneToManyElementSlotState(@NonNull Object eObject, @NonNull EReference eFeature, @NonNull Object eAggregator) {
super(eObject, eFeature, eAggregator);
assert !eFeature.isMany();
assert eFeature.getEOpposite() != null;
assert eFeature.getEOpposite().isMany();
if (eFeature == OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER) {
assert ((EObject)eObject).eContainer() == eAggregator;
}
else {
assert ((EObject)eObject).eGet(eFeature) == eAggregator;
}
}
@Override
public synchronized void assigned(@NonNull Object eObject, @NonNull EStructuralFeature eFeature, @Nullable Object ecoreValue) {
if (!isAssigned() && (ecoreValue != null)) {
EObject eOpposite = (EObject) ecoreValue;
EReference eOppositeReference = ((EReference)eFeature).getEOpposite();
if (eFeature == OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER) {
eOppositeReference = ((EObject)eObject).eContainmentFeature();
assert eOppositeReference != null;
SlotState aggregatorSlotState = getSlotState(eOpposite, eOppositeReference);
aggregatorSlotState.assigned(eOpposite, eOppositeReference, eObject);
}
else {
assert eOppositeReference != null;
OneToManyAggregatorSlotState aggregatorSlotState = (OneToManyAggregatorSlotState) getSlotState(eOpposite, eOppositeReference);
aggregatorSlotState.assignedElement(eOpposite, eOppositeReference, eObject);
}
}
assigned(eObject, eFeature, ecoreValue);
}
@Override
public SlotState.@NonNull Incremental getPrimarySlotState() {
EObject eOpposite = (EObject) getValue();
assert eOpposite != null;
EReference eOppositeReference = ((EReference)eFeature).getEOpposite();
if (eFeature == OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER) {
eOppositeReference = ((EObject)eObject).eContainmentFeature();
assert eOppositeReference != null;
return getSlotState(eOpposite, eOppositeReference);
}
else {
assert eOppositeReference != null;
return getSlotState(eOpposite, eOppositeReference);
}
}
}
/**
* SlotState describing a 1:1 Object navigation. Both ends are assigned exactly once. The remote assignment
* may be null.
* <br>
* Lifecycle 1: write first
* Create due to
* - assign of possibly null eOpposite => ASSIGNED
* Thereafter
* - get of either end ASSIGNED => ASSIGNED
* - (assign of either end is an ignored error)
* <br>
* Lifecycle 2: read first
* Create due to
* - get of other end => ASSIGNABLE_BLOCKED
* Unblock due to
* - assign of a further element to the aggregator => ASSIGNABLE_BLOCKED => ASSIGNED
* Thereafter
* - get of either end ASSIGNED => ASSIGNED
* - (assign of either end is an ignored error)
*/
class OneToOneSlotState extends BasicSlotState
{
/* public static @NonNull <G,S> SlotState createContainer(@NonNull ObjectManager objectManager,
@NonNull EObject eObject, @NonNull EReference eFeature, @Nullable EReference eOppositeFeature, @Nullable EObject eOpposite) {
Map<EStructuralFeature, SlotState> oppositeObjectState = null;
if (eOpposite != null) {
oppositeObjectState = objectManager.getObjectState(eObject);
SlotState slotState = oppositeObjectState.get(eOppositeFeature);
if (slotState != null) {
return slotState;
}
}
SlotState slotState = new OneToOneSlotState(eObject, eFeature, eOpposite);
if (oppositeObjectState != null) {
oppositeObjectState.put(eOppositeFeature, slotState);
}
return slotState;
} */
public OneToOneSlotState(@NonNull Object eObject, @NonNull EReference eFeature) {
super(eObject, eFeature);
assert !eFeature.isMany();
if (eFeature.isContainer()) {
// assert eObject.eContainer() == eOpposite;
}
else if (eFeature.isContainment()) {
// assert eOpposite != null;
// assert eObject == eOpposite.eContainer();
}
else if (eFeature == OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER) {
// slotState = new OneToOneSlotState(eObject, eReference);
}
else {
assert eFeature.getEOpposite() != null;
assert !eFeature.getEOpposite().isMany();
}
}
private OneToOneSlotState(@NonNull Object eObject, @NonNull EReference eFeature, @Nullable Object eOpposite) {
super(eObject, eFeature, eOpposite);
assert !eFeature.isMany();
if (eFeature.isContainer()) {
assert ((EObject)eObject).eContainer() == eOpposite;
}
else if (eFeature.isContainment()) {
assert eOpposite != null;
assert eObject == ((EObject)eOpposite).eContainer();
}
else {
assert eFeature.getEOpposite() != null;
assert !eFeature.getEOpposite().isMany();
assert ((EObject)eObject).eGet(eFeature) == eOpposite;
}
}
@Override
public void assigned(@NonNull Object eObject, @NonNull EStructuralFeature eFeature, @Nullable Object ecoreValue) {
assigned(IncrementalObjectManager.this, eObject, eFeature, ecoreValue);
}
}
/**
* Simple SlotState describing a DataType element or 1:1 Object navigation.
*/
class SimpleSlotState extends BasicSlotState
{
public SimpleSlotState(@NonNull Object eObject, @NonNull EStructuralFeature eFeature) {
super(eObject, eFeature);
}
public SimpleSlotState(@NonNull Object eObject, @NonNull EStructuralFeature eFeature, @Nullable Object ecoreValue) {
super(eObject, eFeature, ecoreValue);
}
@Override
public void assigned(@NonNull Object eObject, @NonNull EStructuralFeature eFeature, @Nullable Object ecoreValue) {
assigned(IncrementalObjectManager.this, eObject, eFeature, ecoreValue);
}
}
protected final boolean debugTracing = AbstractTransformer.INVOCATIONS.isActive();
/**
* This unpleasant Map of Maps is a pathfinder before embarking on slotted objects that merge user and overhead
* in a single object. The first map is then a null lookup and the nested map is an index within the object.
*/
private Map<@NonNull Object, @NonNull Map<@NonNull EStructuralFeature, @NonNull BasicSlotState>> object2feature2slotState = new HashMap<@NonNull Object, @NonNull Map<@NonNull EStructuralFeature, @NonNull BasicSlotState>>();
public IncrementalObjectManager(@NonNull IncrementalInvocationManager invocationManager) {
super(invocationManager);
}
@Override
public synchronized void assigned(@NonNull Object eObject, /*@NonNull*/ EStructuralFeature eFeature, @Nullable Object ecoreValue, @Nullable Object childKey) {
assert eFeature != null;
if (debugTracing) {
AbstractTransformer.INVOCATIONS.println("assigned " + eFeature.getEContainingClass().getName() + "::" + eFeature.getName() + " for " + eObject + " = " + ecoreValue);
}
Map<EStructuralFeature, BasicSlotState> objectState = getObjectState(eObject);
BasicSlotState slotState = objectState.get(eFeature);
if (slotState != null) {
slotState.assigned(eObject, eFeature, ecoreValue);
}
else {
if (eFeature instanceof EAttribute) {
slotState = new SimpleSlotState(eObject, eFeature, ecoreValue);
}
else {
EReference eReference = (EReference)eFeature;
EReference eOppositeReference = eReference.getEOpposite();
if (eOppositeReference != null) {
// if (ecoreValue != null) {
// Map<EStructuralFeature, SlotState> oppositeObjectState = getObjectState((EObject) ecoreValue);
// SlotState oppositeSlotState = oppositeObjectState.get(eOppositeReference);
// }
if (eReference.isMany()) {
assert ecoreValue != null;
if (eOppositeReference.isMany()) {
slotState = createManyToManySlotState(eObject, eReference, eOppositeReference);
}
else {
slotState = createOneToManyAggregatorSlotState(eObject, eReference, eOppositeReference, ecoreValue);
}
}
else if (ecoreValue != null) {
if (eOppositeReference.isMany()) {
slotState = createOneToManyElementSlotState(eObject, eReference, eOppositeReference, ecoreValue);
}
// else if (isIncremental) {
// slotState = AbstractTransformerInternal.OneToOneSlotState.create(this, eObject, eReference, eOppositeReference, ecoreValue);
// }
}
}
else if (eReference.isContainment()) {
assert ecoreValue != null;
eOppositeReference = OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER;
assert eOppositeReference != null;
if (eReference.isMany()) {
slotState = createOneToManyAggregatorSlotState(eObject, eReference, eOppositeReference, ecoreValue);
}
else {
Map<EStructuralFeature, BasicSlotState> oppositeObjectState = getObjectState(ecoreValue);
slotState = oppositeObjectState.get(eOppositeReference);
if (slotState != null) {
slotState.assigned(ecoreValue, eOppositeReference, eObject);
}
else {
slotState = createOneToOneSlotState(eObject, eReference, eOppositeReference, ecoreValue);
}
}
}
// else if (eReference == OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER) {
// slotState = OneToOneSlotState.create(this, eObject, eReference, eOppositeReference, ecoreValue);
// }
else { // Unidirectional non-containment EReference
slotState = new SimpleSlotState(eObject, eFeature, ecoreValue);
}
}
objectState.put(eFeature, slotState);
}
}
@Override
public void assigned(Invocation.@NonNull Incremental invocation, @NonNull Object eObject, EStructuralFeature eFeature, @Nullable Object ecoreValue, @Nullable Object childKey) {
assigned(eObject, eFeature, ecoreValue, childKey);
assert eFeature != null;
BasicSlotState slotState = getSlotState(eObject, eFeature);
invocation.addWriteSlot(slotState);
}
@NonNull BasicSlotState createManyToManySlotState(
@NonNull Object eObject, @NonNull EReference eFeature, @NonNull EReference eOppositeFeature) {
throw new UnsupportedOperationException();
}
@NonNull BasicSlotState createOneToManyAggregatorSlotState(
@NonNull Object eObject, @NonNull EReference eFeature, @NonNull EReference eOppositeFeature, @Nullable Object eContents) {
if (eContents != null) {
// SlotState containedSlotState = objectManager.getSlotState(eContent, eOppositeFeature);
// containedSlotState.assigned(objectManager, eContent, eOppositeFeature, eObject);
}
return new OneToManyAggregatorSlotState(eObject, eFeature, eContents);
}
@NonNull BasicSlotState createOneToManyElementSlotState(
@NonNull Object eObject, @NonNull EReference eFeature, @NonNull EReference eOppositeFeature, @NonNull Object eAggregator) {
OneToManyAggregatorSlotState aggregatorSlotState = (OneToManyAggregatorSlotState) getSlotState(eAggregator, eOppositeFeature);
aggregatorSlotState.assignedElement(eAggregator, eOppositeFeature, eObject);
return new OneToManyElementSlotState(eObject, eFeature, eAggregator);
}
@NonNull <G,S> BasicSlotState createOneToOneSlotState(
@NonNull Object eObject, @NonNull EReference eFeature, @NonNull EReference eOppositeFeature, @Nullable Object eOpposite) {
Map<EStructuralFeature, BasicSlotState> oppositeObjectState = null;
if (eOpposite != null) {
oppositeObjectState = getObjectState(eOpposite);
BasicSlotState slotState = oppositeObjectState.get(eOppositeFeature);
if (slotState != null) {
return slotState;
}
}
BasicSlotState slotState = new OneToOneSlotState(eObject, eFeature, eOpposite);
if (oppositeObjectState != null) {
oppositeObjectState.put(eOppositeFeature, slotState);
}
return slotState;
}
@Override
public void created(Invocation.@NonNull Incremental invocation, @NonNull Object eObject) {
invocation.addCreatedObject(eObject);
}
public @NonNull Map<EStructuralFeature, BasicSlotState> getObjectState(@NonNull Object eObject) {
Map<@NonNull EStructuralFeature, @NonNull BasicSlotState> feature2state = object2feature2slotState.get(eObject);
if (feature2state == null) {
feature2state = new HashMap<@NonNull EStructuralFeature, @NonNull BasicSlotState>();
object2feature2slotState.put(eObject, feature2state);
}
return feature2state;
}
@Override
public @NonNull Iterable<@NonNull ? extends Object> getObjects() {
return object2feature2slotState.keySet();
}
public synchronized @NonNull BasicSlotState getSlotState(@NonNull Object eObject, @NonNull EStructuralFeature eFeature) {
assert eFeature != null;
Map<EStructuralFeature, BasicSlotState> objectState = getObjectState(eObject);
BasicSlotState slotState = objectState.get(eFeature);
if (slotState == null) {
if (eFeature instanceof EAttribute) {
slotState = new SimpleSlotState(eObject, eFeature);
}
else {
EReference eReference = (EReference)eFeature;
EReference eOppositeReference = eReference.getEOpposite(); // FIXME there is always a Pivot opposite
if (eOppositeReference != null) {
if (eReference.isMany()) {
if (eOppositeReference.isMany()) {
slotState = new ManyToManySlotState(eObject, eReference);
}
else {
slotState = new OneToManyAggregatorSlotState(eObject, eReference);
}
}
else {
if (eOppositeReference.isMany()) {
slotState = new OneToManyElementSlotState(eObject, eReference);
}
else {
slotState = new OneToOneSlotState(eObject, eReference);
}
}
}
else if (eReference.isContainment()) {
if (eReference.isMany()) {
slotState = new OneToManyAggregatorSlotState(eObject, eReference);
}
else {
slotState = new OneToOneSlotState(eObject, eReference);
}
}
else if (eReference == OCLstdlibPackage.Literals.OCL_ELEMENT__OCL_CONTAINER) {
slotState = new OneToManyElementSlotState(eObject, eReference); //FIXME may be many
}
else { // Unidirectional non-containment EReference
slotState = new SimpleSlotState(eObject, eFeature);
}
}
objectState.put(eFeature, slotState);
}
return slotState;
}
@Override
public @NonNull Iterable<@NonNull ? extends SlotState> getSlotStates(@NonNull Object object) {
Map<@NonNull EStructuralFeature, @NonNull BasicSlotState> feature2slotState = object2feature2slotState.get(object);;
return feature2slotState != null ? feature2slotState.values() : EMPTY_SLOT_STATE_LIST;
}
@Override
public synchronized void getting(@NonNull Object eObject, /*@NonNull*/ EStructuralFeature eFeature, boolean isOpposite) {
assert eFeature != null;
if (debugTracing) {
AbstractTransformer.INVOCATIONS.println("getting " + eFeature.getEContainingClass().getName() + "::" + eFeature.getName() + " for " + eObject);
}
SlotState slotState = getSlotState(eObject, eFeature);
slotState.getting(eObject, eFeature);
}
@Override
public void got(Invocation.@NonNull Incremental invocation, @NonNull Object eObject, /*@NonNull*/ EStructuralFeature eFeature, @Nullable Object ecoreValue) {
assert eFeature != null;
BasicSlotState slotState = getSlotState(eObject, eFeature);
invocation.addReadSlot(slotState);
}
}