blob: 2eef2bc2b7bc9f9e25e18d9dd29e4d61755aedba [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2019 Willink Transformations and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* E.D.Willink - Initial API and implementation
*******************************************************************************/
package org.eclipse.qvtd.runtime.evaluation;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jdt.annotation.NonNull;
public class EReferenceAnalysis
{
// protected final @NonNull EClassAnalysis eClassAnalysis;
protected final @NonNull AbstractTypedModelInstance typedModelInstance;
protected final @NonNull ModelsManager modelsManager;
/**
* The analyzed EReference.
*/
protected final @NonNull EReference eReference;
private final boolean isContainment;
private final boolean isMany;
private final boolean isResolveProxies;
private final int oppositePropertyIndex;
public EReferenceAnalysis(@NonNull EClassAnalysis eClassAnalysis, @NonNull EReference eReference, int oppositePropertyIndex) {
// this.eClassAnalysis = eClassAnalysis;
this.typedModelInstance = eClassAnalysis.getTypedModelInstance();
this.modelsManager = typedModelInstance.getModelsManager();
this.eReference = eReference;
this.isContainment = eReference.isContainment();
this.isMany = eReference.isMany();
this.isResolveProxies = eReference.isResolveProxies();
this.oppositePropertyIndex = oppositePropertyIndex;
assert !isContainment || (oppositePropertyIndex < 0);
}
public void traverseFrom(@NonNull EObject eObject) {
if (!isMany) {
Object object = eObject.eGet(eReference, true);
if (object != null) {
traverseFromTo(eObject, (EObject)object);
}
}
else if (eObject.eIsSet(eReference)) { // Avoid creating an empty list
@SuppressWarnings("unchecked")
List<@NonNull EObject> list = (List<@NonNull EObject>)eObject.eGet(eReference, true);
for (@NonNull EObject object : list) {
traverseFromTo(eObject, object);
}
}
}
private void traverseFromTo(@NonNull EObject fromEObject, @NonNull EObject toEObject) {
if (isResolveProxies) {
Resource eResource = toEObject.eResource();
if (eResource != null) { // FIXME faster rejection of known resources, particularly the current resource
typedModelInstance.addInputResource(eResource);
}
}
if (isContainment) {
typedModelInstance.getEClassAnalysis(toEObject).traverseChild(toEObject);
}
else if (oppositePropertyIndex >= 0) {
Map<@NonNull Object, @NonNull Object>[] object2oppositeObject2 = modelsManager.getObject2oppositeObject();
assert object2oppositeObject2 != null;
object2oppositeObject2[oppositePropertyIndex].put(toEObject, fromEObject);
}
}
public void untraverseFrom(@NonNull EObject eObject) {
if (oppositePropertyIndex >= 0) {
@NonNull Map<@NonNull Object, @NonNull Object>[] object2oppositeObject2 = modelsManager.getObject2oppositeObject();
EReference @NonNull [] propertyIndex2eReference2 = modelsManager.getPropertyIndex2eReference();
EReference eReference = propertyIndex2eReference2[oppositePropertyIndex];
if (eReference != null) {
Object object = eObject.eGet(eReference);
assert object != null;
object2oppositeObject2[oppositePropertyIndex].remove(object);
}
}
}
}