blob: 6db166ea0f38992e3d21d57634071532682b7d79 [file] [log] [blame]
/**
* Copyright (c) 2010 Henning Heitkoetter.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Henning Heitkoetter - initial API and implementation
*/
package org.eclipse.bpmn2.util;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.bpmn2.Bpmn2Package;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.util.BasicInternalEList;
import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
/**
* A cross reference adapter for resolving virtual opposite references.
*
* It observes a set of references and is able to construct opposite references for these references.
* @author Henning Heitkoetter
*
*/
public class Bpmn2OppositeReferenceAdapter extends ECrossReferenceAdapter {
public static final Map<EReference, EReference> DEFAULT_OBSERVED_REFERENCES;
static {
DEFAULT_OBSERVED_REFERENCES = new HashMap<EReference, EReference>();
DEFAULT_OBSERVED_REFERENCES.put(Bpmn2Package.Literals.FLOW_ELEMENT__CATEGORY_VALUE_REF,
Bpmn2Package.Literals.CATEGORY_VALUE__CATEGORIZED_FLOW_ELEMENTS);
DEFAULT_OBSERVED_REFERENCES.put(Bpmn2Package.Literals.CONVERSATION_LINK__SOURCE_REF,
Bpmn2Package.Literals.INTERACTION_NODE__OUTGOING_CONVERSATION_LINKS);
DEFAULT_OBSERVED_REFERENCES.put(Bpmn2Package.Literals.CONVERSATION_LINK__TARGET_REF,
Bpmn2Package.Literals.INTERACTION_NODE__INCOMING_CONVERSATION_LINKS);
}
/**
* A map from references that will be observed by this adapter to their (virtual) opposite reference.
*/
protected Map<EReference, EReference> observedRefToOpposite = new HashMap<EReference, EReference>();
public Bpmn2OppositeReferenceAdapter(Map<EReference, EReference> observedRefToOpposite) {
super();
this.observedRefToOpposite.putAll(observedRefToOpposite);
}
public Bpmn2OppositeReferenceAdapter() {
this(DEFAULT_OBSERVED_REFERENCES);
}
public EReference putObservedRefToOpposite(EReference key, EReference value) {
return observedRefToOpposite.put(key, value);
}
public EReference removeObservedRef(Object key) {
return observedRefToOpposite.remove(key);
}
/**
* Returns true if the reference is being watched by this adapter.
*/
@Override
protected boolean isIncluded(EReference eReference) {
return observedRefToOpposite.containsKey(eReference);
}
/**
* Returns a list that holds the opposite elements of the given reference for the given owner.
* The opposite elements are those of type E that have the reference to owner.
*
* The collection corresponding to opposite in the following picture is returned,
* for given owner and reference.
* <pre>
* <b>opposite</b> reference
* E ----------------------------- owner
* </pre>
*
* reference has to be a key of the map observedRefToOpposite.
* @param <E>
* @param <E> The type of the elements in the collection.
* @param dataClass The class of the elements in the collection.
* @param owner The object whose list is retrieved.
* @param reference The reference whose opposite reference is retrieved.
* @return The opposite of reference for owner.
*/
public <E> List<E> getOppositeList(Class<E> dataClass, InternalEObject owner,
EReference reference) {
EReference opposite = observedRefToOpposite.get(reference);
if (opposite == null)
throw new IllegalArgumentException("This reference is not observed by this adapter: "
+ reference.toString());
List<E> result = new BasicInternalEList<E>(dataClass);
for (Setting cur : getNonNavigableInverseReferences(owner, false)) {
if (cur.getEStructuralFeature().equals(reference))
result.add(dataClass.cast(cur.getEObject()));
}
return result;
}
}