PropertiesLinkingService.java
/**
* Copyright (c) 2004-2025 Carnegie Mellon University and others. (see Contributors file).
* All Rights Reserved.
*
* NO WARRANTY. ALL MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY
* KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE
* OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT
* MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
*
* This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
* SPDX-License-Identifier: EPL-2.0
*
* Created, in part, with funding and support from the United States Government. (see Acknowledgments file).
*
* This program includes and/or can make use of certain third party source code, object code, documentation and other
* files ("Third Party Software"). The Third Party Software that is used by this program is dependent upon your system
* configuration. By using this program, You agree to comply with any and all relevant Third Party Software terms and
* conditions contained in any such Third Party Software or separate license file distributed with such Third Party
* Software. The parties who own the Third Party Software ("Third Party Licensors") are intended third party benefici-
* aries to this license with respect to the terms applicable to their Third Party Software. Third Party Software li-
* censes only apply to the Third Party Software and not any other portion of this program or this program as a whole.
*/
package org.osate.xtext.aadl2.properties.linking;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.xtext.linking.impl.DefaultLinkingService;
import org.eclipse.xtext.linking.impl.IllegalNodeException;
import org.eclipse.xtext.naming.IQualifiedNameConverter;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.nodemodel.INode;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.scoping.IScope;
import org.osate.aadl2.Aadl2Package;
import org.osate.aadl2.AadlPackage;
import org.osate.aadl2.AbstractSubcomponent;
import org.osate.aadl2.BasicProperty;
import org.osate.aadl2.BasicPropertyAssociation;
import org.osate.aadl2.BehavioredImplementation;
import org.osate.aadl2.CallContext;
import org.osate.aadl2.Classifier;
import org.osate.aadl2.ComponentClassifier;
import org.osate.aadl2.ComponentPrototype;
import org.osate.aadl2.ComponentPrototypeBinding;
import org.osate.aadl2.ComponentType;
import org.osate.aadl2.ContainedNamedElement;
import org.osate.aadl2.ContainmentPathElement;
import org.osate.aadl2.Context;
import org.osate.aadl2.DataPrototype;
import org.osate.aadl2.Element;
import org.osate.aadl2.EnumerationLiteral;
import org.osate.aadl2.EnumerationType;
import org.osate.aadl2.Feature;
import org.osate.aadl2.FeatureGroup;
import org.osate.aadl2.FeatureGroupPrototype;
import org.osate.aadl2.FeatureGroupPrototypeActual;
import org.osate.aadl2.FeatureGroupPrototypeBinding;
import org.osate.aadl2.FeatureGroupType;
import org.osate.aadl2.FeatureType;
import org.osate.aadl2.FlowEnd;
import org.osate.aadl2.Generalization;
import org.osate.aadl2.ListValue;
import org.osate.aadl2.ModalPropertyValue;
import org.osate.aadl2.Mode;
import org.osate.aadl2.ModeBinding;
import org.osate.aadl2.NamedElement;
import org.osate.aadl2.NamedValue;
import org.osate.aadl2.Namespace;
import org.osate.aadl2.NumberType;
import org.osate.aadl2.NumberValue;
import org.osate.aadl2.NumericRange;
import org.osate.aadl2.PackageRename;
import org.osate.aadl2.PackageSection;
import org.osate.aadl2.PrivatePackageSection;
import org.osate.aadl2.Property;
import org.osate.aadl2.PropertyAssociation;
import org.osate.aadl2.PropertyConstant;
import org.osate.aadl2.PropertySet;
import org.osate.aadl2.PropertyType;
import org.osate.aadl2.Prototype;
import org.osate.aadl2.PrototypeBinding;
import org.osate.aadl2.PublicPackageSection;
import org.osate.aadl2.RangeType;
import org.osate.aadl2.RangeValue;
import org.osate.aadl2.RecordType;
import org.osate.aadl2.Subcomponent;
import org.osate.aadl2.SubcomponentType;
import org.osate.aadl2.SubprogramAccess;
import org.osate.aadl2.SubprogramCall;
import org.osate.aadl2.SubprogramGroupAccess;
import org.osate.aadl2.SubprogramGroupSubcomponent;
import org.osate.aadl2.SubprogramSubcomponent;
import org.osate.aadl2.ThreadSubcomponent;
import org.osate.aadl2.UnitLiteral;
import org.osate.aadl2.UnitsType;
import org.osate.aadl2.modelsupport.ResolvePrototypeUtil;
import org.osate.aadl2.modelsupport.util.AadlUtil;
import org.osate.xtext.aadl2.properties.util.PSNode;
import com.google.inject.Inject;
public class PropertiesLinkingService extends DefaultLinkingService {
@Inject
private IQualifiedNameConverter qualifiedNameConverter;
public PropertiesLinkingService() {
super();
}
private static PSNode psNode = new PSNode();
private final String PLUGIN_ID = "org.osate.xtext.aadl2";
public EObject getIndexedObject(EObject context, EReference reference, String crossRefString) {
psNode.setText(crossRefString);
EObject res = null;
try {
List<EObject> el;
el = super.getLinkedObjects(context, reference, psNode);
res = (el.isEmpty() ? null : el.get(0));
if (res != null && res.eIsProxy()) {
res = EcoreUtil.resolve(res, context);
if (res.eIsProxy()) {
return null;
}
}
} catch (Exception e) {
IStatus status = new Status(IStatus.ERROR, PLUGIN_ID, e.getMessage(), e);
StatusManager manager = StatusManager.getManager();
manager.handle(status, StatusManager.LOG);
}
return res;
// XXX phf: lookup in global index without regard to project dependencies
// EObject res = EMFIndexRetrieval.getEObjectOfType(context,reference.getEReferenceType(), crossRefString);
// return res;
}
/**
* copy of a method from within Xtext. Needed to change getSingleElement to getElements to see if we have doubles
* in different files and the same project or in different projects.
* @param context
* @param reference
* @param crossRefString
* @return
*/
public Iterable<IEObjectDescription> getIndexedObjects(EObject context, EReference reference,
String crossRefString) {
// List<EObject> el;
try {
if (crossRefString != null && !crossRefString.equals("")) {
final IScope scope = getScope(context, reference);
QualifiedName qualifiedLinkName = qualifiedNameConverter.toQualifiedName(crossRefString);
Iterable<IEObjectDescription> eObjectDescriptions = scope.getElements(qualifiedLinkName);
return eObjectDescriptions;
}
// el = super.getLinkedObjects(context, reference, psNode);
} catch (Exception e) {
return null;
}
// EObject res = (el.isEmpty()?null: el.get(0));
// if (res != null&&res.eIsProxy()){
// res = EcoreUtil.resolve(res,context);
// if (res.eIsProxy()) return null;
// }
return null;
}
@Override
public String getCrossRefNodeAsString(INode node) throws IllegalNodeException {
if (node instanceof PSNode) {
return getLinkingHelper().getCrossRefNodeAsString(node, false);
} else {
return getLinkingHelper().getCrossRefNodeAsString(node, true);
}
}
/**
* returns the first linked object
*/
@Override
public List<EObject> getLinkedObjects(EObject context, EReference reference, INode node)
throws IllegalNodeException {
final EClass requiredType = reference.getEReferenceType();
if (requiredType == null) {
return Collections.<EObject> emptyList();
}
EObject searchResult = null;
final EClass cl = Aadl2Package.eINSTANCE.getClassifier();
final EClass sct = Aadl2Package.eINSTANCE.getSubcomponentType();
final EClass pt = Aadl2Package.eINSTANCE.getPropertyType();
final String name = getCrossRefNodeAsString(node);
if (sct.isSuperTypeOf(requiredType) || cl.isSuperTypeOf(requiredType)) {
// XXX: this code can be replicated in Aadl2LinkingService as it is called often in the core
// resolve classifier reference
EObject e = findClassifier(context, reference, name);
if (e != null) {
// the result satisfied the expected class
return Collections.singletonList(e);
}
if (!(context instanceof Generalization) && sct.isSuperTypeOf(requiredType)) {
// need to resolve prototype
EObject res = AadlUtil.getContainingClassifier(context).findNamedElement(name);
if (Aadl2Package.eINSTANCE.getDataPrototype() == reference) {
if (res instanceof DataPrototype) {
searchResult = res;
}
} else if (res instanceof ComponentPrototype) {
searchResult = res;
}
}
} else if (Aadl2Package.eINSTANCE.getModelUnit() == requiredType) {
AadlPackage pack = findAadlPackage(context, name, reference);
if (pack != null) {
searchResult = pack;
} else {
PropertySet ps = findPropertySet(context, name, reference);
if (ps != null) {
searchResult = ps;
}
}
} else if (Aadl2Package.eINSTANCE.getAadlPackage() == requiredType) {
AadlPackage pack = findAadlPackage(context, name, reference);
if (pack != null) {
searchResult = pack;
}
} else if (Aadl2Package.eINSTANCE.getPropertySet() == requiredType) {
PropertySet ps = findPropertySet(context, name, reference);
if (ps != null) {
searchResult = ps;
}
} else if (Aadl2Package.eINSTANCE.getFeature().isSuperTypeOf(requiredType)) {
if (context instanceof Feature) {
// Feature referenced in feature refinement
Classifier ns = AadlUtil.getContainingClassifier(context);
// we need to resolve a refinement
if (ns.getExtended() != null) {
EObject res = ns.getExtended().findNamedElement(name);
if (res != null && res instanceof Feature) {
searchResult = res;
}
} else {
return Collections.emptyList();
}
} else if (context instanceof FlowEnd) {
FlowEnd flowEnd = (FlowEnd) context;
FlowEnd prev = flowEnd.getContext();
Context ctx = null;
if (prev != null) {
ctx = (Context) prev.getFeature();
}
searchResult = findElementInContext(flowEnd, ctx, name, Feature.class);
}
} else if (Aadl2Package.eINSTANCE.getSubcomponent().isSuperTypeOf(requiredType)) {
// if context Subcomponent then find in extension source (refined
// to)
// prototype binding as context
Classifier ns = AadlUtil.getContainingClassifier(context);
if (context instanceof Subcomponent) {
// we need to resolve a refinement
if (ns.getExtended() != null) {
ns = ns.getExtended();
} else {
return Collections.emptyList();
}
}
EObject res = ns.findNamedElement(name);
if (res instanceof Subcomponent) {
searchResult = res;
}
} else if (Aadl2Package.eINSTANCE.getProperty() == requiredType) {
// look for property definition in property set
return findPropertyDefinitionAsList(context, reference, name);
} else if (Aadl2Package.eINSTANCE.getAbstractNamedValue() == requiredType) {
// AbstractNamedValue: constant reference, property definition reference, unit literal, enumeration literal
if (context instanceof NamedValue) {
List<EObject> res = Collections.EMPTY_LIST;
if (name.indexOf("::") == -1) {
// names without qualifier. Must be enum/unit literal
res = findEnumLiteralAsList(context, reference, name);
if (res.isEmpty()) {
res = findUnitLiteralAsList(context, reference, name);
}
}
if (res.isEmpty()) {
res = findPropertyConstant(context, reference, name);
}
if (res.isEmpty()) {
res = findPropertyDefinitionAsList(context, reference, name);
}
return res;
}
} else if (Aadl2Package.eINSTANCE.getBasicProperty() == requiredType) {
// look for record field definition
if (context instanceof BasicPropertyAssociation) {
BasicPropertyAssociation bpa = (BasicPropertyAssociation) context;
// TODO: Need to check that the type of the record field is
// correct for the value.
Element parent = bpa.getOwner();
while (parent != null
&& !(parent instanceof BasicPropertyAssociation || parent instanceof PropertyAssociation
|| parent instanceof Property || parent instanceof PropertyConstant)) {
parent = parent.getOwner();
}
PropertyType propertyType = null;
if (parent instanceof BasicPropertyAssociation) {
BasicProperty bp = ((BasicPropertyAssociation) parent).getProperty();
if (bp != null) {
propertyType = bp.getPropertyType();
}
} else if (parent instanceof PropertyAssociation) {
Property pd = ((PropertyAssociation) parent).getProperty();
if (pd != null) {
propertyType = pd.getPropertyType();
}
} else if (parent instanceof Property) {
propertyType = ((Property) parent).getPropertyType();
} else if (parent instanceof PropertyConstant) {
propertyType = ((PropertyConstant) parent).getPropertyType();
}
propertyType = AadlUtil.getBasePropertyType(propertyType);
if (propertyType != null && propertyType instanceof RecordType) {
BasicProperty rf = (BasicProperty) ((RecordType) propertyType).findNamedElement(name);
if (rf != null) {
searchResult = rf;
}
}
}
} else if (pt.isSuperTypeOf(requiredType)) {
// look for property type in property set
return findPropertyType(context, reference, name);
} else if (Aadl2Package.eINSTANCE.getPropertyConstant() == requiredType) {
// look for property constant in property set
return findPropertyConstant(context, reference, name);
} else if (Aadl2Package.eINSTANCE.getUnitLiteral() == requiredType) {
// look for unit literal pointed to by baseUnit
return findUnitLiteralAsList(context, reference, name);
} else if (Aadl2Package.eINSTANCE.getEnumerationLiteral() == requiredType) {
// look for enumeration literal
return findEnumLiteralAsList(context, reference, name);
} else if (Aadl2Package.eINSTANCE.getMode() == requiredType) {
// referenced by mode transition, inmodes, ModeBinding
EObject res = null;
if (context instanceof ModeBinding) {
if (reference == Aadl2Package.eINSTANCE.getModeBinding_ParentMode()) {
res = AadlUtil.getContainingClassifier(context).findNamedElement(name);
} else if (reference == Aadl2Package.eINSTANCE.getModeBinding_DerivedMode()) {
Subcomponent subcomponent = AadlUtil.getContainingSubcomponent(context);
while (subcomponent.getSubcomponentType() == null && subcomponent.getRefined() != null) {
subcomponent = subcomponent.getRefined();
}
ComponentClassifier subcomponentClassifier = null;
if (subcomponent.getSubcomponentType() instanceof ComponentClassifier) {
subcomponentClassifier = ((ComponentClassifier) subcomponent.getSubcomponentType());
} else if (subcomponent.getSubcomponentType() instanceof ComponentPrototype) {
subcomponentClassifier = findClassifierForComponentPrototype(
AadlUtil.getContainingClassifier(context),
((ComponentPrototype) subcomponent.getSubcomponentType()));
}
if (subcomponentClassifier != null) {
res = subcomponentClassifier.findNamedElement(name);
}
}
} else {
// check about in modes in a contained property association
PropertyAssociation pa = AadlUtil.getContainingPropertyAssociation(context);
if (pa != null && !pa.getAppliesTos().isEmpty()) {
ContainedNamedElement path = pa.getAppliesTos().get(0);
EList<ContainmentPathElement> cpelist = path.getContainmentPathElements();
Subcomponent cpesub = null;
for (ContainmentPathElement containmentPathElement : cpelist) {
if (containmentPathElement.getNamedElement() instanceof Subcomponent) {
cpesub = (Subcomponent) containmentPathElement.getNamedElement();
} else {
break;
}
}
if (cpesub != null) {
if (cpesub.getAllClassifier() != null) {
res = cpesub.getAllClassifier().findNamedElement(name);
}
} else {
res = AadlUtil.getContainingClassifier(context).findNamedElement(name);
}
} else {
if ((pa != null) && (pa.getOwner() instanceof Subcomponent)) {
Subcomponent subco = (Subcomponent) pa.getOwner();
if (subco.getAllClassifier() != null) {
res = subco.getAllClassifier().findNamedElement(name);
}
} else {
res = AadlUtil.getContainingClassifier(context).findNamedElement(name);
}
}
}
if (res != null && res instanceof Mode) {
searchResult = res;
}
} else if (Aadl2Package.eINSTANCE.getNamedElement() == requiredType) {
// containment path element
if (context instanceof ContainmentPathElement) {
EObject res = null;
if (((ContainmentPathElement) context).getOwner() instanceof ContainmentPathElement) {
// find next element in namespace of previous element
ContainmentPathElement el = (ContainmentPathElement) ((ContainmentPathElement) context).getOwner();
NamedElement ne = el.getNamedElement();
if (ne instanceof Subcomponent) {
Subcomponent subcomponent = (Subcomponent) ne;
while (subcomponent.getSubcomponentType() == null && subcomponent.getRefined() != null) {
subcomponent = subcomponent.getRefined();
}
ComponentClassifier ns = null;
if (subcomponent.getSubcomponentType() instanceof ComponentClassifier) {
ns = (ComponentClassifier) subcomponent.getSubcomponentType();
} else if (subcomponent.getSubcomponentType() instanceof ComponentPrototype) {
ns = ResolvePrototypeUtil.resolveComponentPrototype(
(ComponentPrototype) subcomponent.getSubcomponentType(), el);
}
if (ns != null) {
res = ns.findNamedElement(name);
if (res == null
&& (ne instanceof ThreadSubcomponent || ne instanceof SubprogramSubcomponent
|| ne instanceof AbstractSubcomponent)
&& ns instanceof BehavioredImplementation) {
res = AadlUtil.findNamedElementInList(((BehavioredImplementation) ns).subprogramCalls(),
name);
}
}
} else if (ne instanceof FeatureGroup) {
FeatureGroup featureGroup = (FeatureGroup) ne;
while (featureGroup.getFeatureType() == null
&& featureGroup.getRefined() instanceof FeatureGroup) {
featureGroup = (FeatureGroup) featureGroup.getRefined();
}
FeatureGroupType ns = null;
if (featureGroup.getFeatureType() instanceof FeatureGroupType) {
ns = (FeatureGroupType) featureGroup.getFeatureType();
} else if (featureGroup.getFeatureType() instanceof FeatureGroupPrototype) {
ns = ResolvePrototypeUtil.resolveFeatureGroupPrototype(
(FeatureGroupPrototype) featureGroup.getFeatureType(), el);
}
if (ns != null) {
res = ns.findNamedElement(name);
}
}
} else {
// the first containment path element
Classifier ns = null;
PropertyAssociation containingPropertyAssociation = AadlUtil
.getContainingPropertyAssociation(context);
if (containingPropertyAssociation != null) {
// need to make sure we look in the correct name space
if (containingPropertyAssociation.getOwner() instanceof Subcomponent) {
Subcomponent subcomponent = (Subcomponent) containingPropertyAssociation.getOwner();
while (subcomponent.getSubcomponentType() == null && subcomponent.getRefined() != null) {
subcomponent = subcomponent.getRefined();
}
if (subcomponent.getSubcomponentType() instanceof ComponentClassifier) {
ns = (ComponentClassifier) subcomponent.getSubcomponentType();
} else if (subcomponent.getSubcomponentType() instanceof ComponentPrototype) {
ns = ResolvePrototypeUtil.resolveComponentPrototype(
(ComponentPrototype) subcomponent.getSubcomponentType(),
AadlUtil.getContainingClassifier(context));
}
} else if (containingPropertyAssociation.getOwner() instanceof FeatureGroup) {
FeatureGroup fg = (FeatureGroup) containingPropertyAssociation.getOwner();
while (fg.getFeatureType() == null && fg.getRefined() instanceof FeatureGroup) {
fg = (FeatureGroup) fg.getRefined();
}
if (fg.getFeatureType() instanceof FeatureGroupType) {
ns = (FeatureGroupType) fg.getFeatureType();
} else if (fg.getFeatureType() instanceof FeatureGroupPrototype) {
ns = ResolvePrototypeUtil.resolveFeatureGroupPrototype(
(FeatureGroupPrototype) fg.getFeatureType(),
AadlUtil.getContainingClassifier(context));
}
} else {
ns = containingPropertyAssociation.getContainingClassifier();
}
}
if (ns != null) {
res = ns.findNamedElement(name);
}
}
if (res != null && res instanceof NamedElement) {
searchResult = res;
}
}
} else {
List<EObject> superes = super.getLinkedObjects(context, reference, node);
return superes;
}
if (searchResult != null) {
return Collections.singletonList(searchResult);
}
return Collections.<EObject> emptyList();
}
/**
* Look up package in EMF index or in resource set
* NOTE: the resource set does not have all resources loaded
* @param context Context of reference
* @param name Package name
* @return aadl package or null
*/
public AadlPackage findAadlPackage(EObject context, String name) {
// EReference reference = Aadl2Package.eINSTANCE.getPackageSection_ImportedUnit();
EReference reference = Aadl2Package.eINSTANCE.getPropertySet_ImportedUnit();
return findAadlPackage(context, name, reference);
}
/**
* Look up package in EMF index
* NOTE: the resource set does not have all resources loaded
* @param context Context of reference
* @param name Package name
* @param reference Ereference identifying the type of the reference
* @return aadl package or null
*/
public AadlPackage findAadlPackage(EObject context, String name, EReference reference) {
EObject res = getIndexedObject(context, reference, name);
if (res instanceof AadlPackage) {
return (AadlPackage) res;
}
if (name == null || name.length() == 0) {
return null;
}
return null;
}
/**
* Find referenced Package by resolving renames first and then making sure it is listed in a with clause
* If package name is null or that of the context return containing package
* @param packageName
* @param context location of the package reference
* @return aadl package
*/
public AadlPackage findAadlPackageReference(String packageName, Namespace context) {
if (context instanceof PackageSection
&& (packageName == null || context.getName().equalsIgnoreCase(packageName))) {
return (AadlPackage) ((PackageSection) context).eContainer();
} else {
AadlPackage aadlPackage = null;
if (context instanceof PackageSection) {
aadlPackage = resolvePackageRename(packageName, (PackageSection) context);
if (aadlPackage == null) {
aadlPackage = AadlUtil.findImportedPackage(packageName, context);
}
} else {
aadlPackage = AadlUtil.findImportedPackage(packageName, context);
}
return aadlPackage;
}
}
/**
* resolve package name by looking it up in PackageRename
* @param name package name
* @param context Package section with rename declarations
* @return aadl package or null
*/
public AadlPackage resolvePackageRename(String name, PackageSection context) {
AadlPackage searchResult = resolvePackageRename(name, context.getOwnedPackageRenames());
if (searchResult == null && context instanceof PrivatePackageSection
&& ((AadlPackage) context.eContainer()).getPublicSection() != null) {
PublicPackageSection pubsec = ((AadlPackage) context.eContainer()).getPublicSection();
searchResult = resolvePackageRename(name, pubsec.getOwnedPackageRenames());
}
return searchResult;
}
/**
* find and return renamed package in list of package renames
* @param name package name to be resolved
* @param packageRenames list of package renames
* @return aadl package or null
*/
public AadlPackage resolvePackageRename(String name, EList<PackageRename> packageRenames) {
for (PackageRename namedElement : packageRenames) {
if (namedElement.hasName() && namedElement.getName().equalsIgnoreCase(name)) {
return namedElement.getRenamedPackage();
}
}
return null;
}
/**
* look up property set in EMF index or resource set
* @param context
* @param name
* @return
*/
public PropertySet findPropertySet(Element context, String name) {
EReference reference = Aadl2Package.eINSTANCE.getPropertySet_ImportedUnit();
return findPropertySet(context, name, reference);
}
/**
* look property set up in EMF index, if not found search through resource set
* NOTE: resource set does not have all resources loaded
* @param context
* @param name Property set name
* @param reference EReference used to identify the type of object we are looking for
* @return
*/
public PropertySet findPropertySet(EObject context, String name, EReference reference) {
EObject res = getIndexedObject(context, reference, name);
if (res instanceof PropertySet) {
return (PropertySet) res;
}
if (name == null || name.length() == 0) {
return null;
}
return null;
}
/**
* find the component classifier taking into account rename aliases
* The name may be qualified with a package name
* We do not check whether the referenced package is in the with clause. This is checked separately
* @param context Element any model object that is the context of the reference
* @param name name to be resolved; may be unqualified or qualified with a package name
* @return ComponentClassifier or null
*/
public ComponentClassifier findComponentClassifier(Element context, String name) {
EReference reference = Aadl2Package.eINSTANCE.getComponentPrototype_ConstrainingClassifier();
return (ComponentClassifier) findClassifier(context, reference, name);
}
public FeatureGroupType findFeatureGroupType(Element context, String name) {
EReference reference = Aadl2Package.eINSTANCE.getFeatureGroupPrototype_ConstrainingFeatureGroupType();
return (FeatureGroupType) findClassifier(context, reference, name);
}
public FeatureGroupType findFeatureGroupType(EObject context, String name, EReference reference) {
return (FeatureGroupType) findClassifier(context, reference, name);
}
/**
* find the classifier taking into account rename aliases
* We do not check whether the referenced package is in the with clause. This is checked separately
* This is a helper method for findFeatureGroupType and findComponentClassifier
* @param context classifier reference context
* @param reference identifying attribute of reference
* @param name name to be resolved
* @return Classifier or null
*/
public Classifier findClassifier(EObject context, EReference reference, String name) {
Namespace scope = AadlUtil.getContainingTopLevelNamespace(context);
EObject e = getIndexedObject(context, reference, name);
if (e != null && e instanceof Classifier && reference.getEReferenceType().isSuperTypeOf(e.eClass())) {
// the result satisfied the expected class
Namespace ns = AadlUtil.getContainingTopLevelNamespace(e);
if (ns instanceof PrivatePackageSection && scope != ns) {
return null;
}
return (Classifier) e;
}
// need to do a local lookup as it was not found in the index.
String packname = null;
String cname = name;
final int idx = name.lastIndexOf("::");
if (idx != -1) {
packname = name.substring(0, idx);
cname = name.substring(idx + 2);
// if rename is not a package rename, but component type rename then all is treated as component ID
if (cname.equalsIgnoreCase("all")) {
return null;
}
}
// NOTE: checking whether the referenced package is imported is done by the validator.
if (context instanceof NamedElement) {
// if we have a NamedElement (e.g., a renames) without a name and we are looking for the reference in own package
// then stop. Otherwise we have a cycle.
if (((NamedElement) context).getName() == null) {
if (packname == null || scope.getName().equalsIgnoreCase(packname)) {
return null;
}
}
}
if (e == null && scope instanceof PackageSection) {
// the reference is from inside a package section. Lookup by identifier with or without qualification
e = findNamedElementInAadlPackage(packname, cname, scope);
if (e != null && e instanceof Classifier && reference.getEReferenceType().isSuperTypeOf(e.eClass())) {
// the result satisfied the expected class
return (Classifier) e;
}
}
return null;
}
/**
* find a named element in a property set based on an optionally qualified name.
* The name is qualified with the property set name, or if unqualified is assumed to be a predeclared property constant
* The context object can be any model object, typically the object that is the context of the reference such as a property definition
* The reference is an EReference pointing to the the named element
* This method is a helper method for the FindPropertyConstant/Type/Definition methods
* @param context Element an AADL model element
* @param reference EReference
* @param name property type name possibly qualified with the property set name
* @return
*/
public EObject findPropertySetElement(EObject context, EReference reference, String name) {
// look for element in property set
String psname = null;
String pname = name;
final int idx = name.lastIndexOf("::");
if (idx != -1) {
psname = name.substring(0, idx);
pname = name.substring(idx + 2);
}
if (psname == null) {
return findNamedElementInPredeclaredPropertySets(pname, context, reference);
} else {
return getIndexedObject(context, reference, name);
}
}
/**
* find property constant based on property constant name.
* The name is qualified with the property set name, or if unqualified is assumed to be a predeclared property constant
* The context object can be any model object, typically the object that is the context of the reference such as a property definition
* @param context Element an AADL model element
* @param name property type name possibly qualified with the property set name
* @return PropertyConstant the property type or null
*/
public PropertyConstant findPropertyConstant(EObject context, String name) {
// look for property constant in property set
EReference reference = Aadl2Package.eINSTANCE.getNamedValue_NamedValue();
EObject e = findPropertySetElement(context, reference, name);
if (e != null && e instanceof PropertyConstant) {
return (PropertyConstant) e;
}
return null;
}
public List<EObject> findPropertyConstant(EObject context, EReference reference, String name) {
// look for property constant in property set
EObject e = findPropertySetElement(context, reference, name);
if (e != null && e instanceof PropertyConstant) {
return Collections.singletonList(e);
}
return Collections.<EObject> emptyList();
}
/**
* find property type based on property name.
* The name is qualified with the property set name, or if unqualified is assumed to be a predeclared property type
* The context object can be any model object, typically the object that is the context of the reference such as a property definition
* @param context Element an AADL model element
* @param name property type name possibly qualified with the property set name
* @return PropertyType the property type or null
*/
public PropertyType findPropertyType(EObject context, String name) {
// look for property type in property set
EReference reference = Aadl2Package.eINSTANCE.getBasicProperty_PropertyType();
EObject e = findPropertySetElement(context, reference, name);
if (e != null && e instanceof PropertyType) {
return (PropertyType) e;
}
return null;
}
public List<EObject> findPropertyType(EObject context, EReference reference, String name) {
// look for property constant in property set
EObject e = findPropertySetElement(context, reference, name);
if (e != null && e instanceof PropertyType) {
return Collections.singletonList(e);
}
return Collections.<EObject> emptyList();
}
/**
* find property definition based on property name.
* The name is qualified with the property set name, or if unqualified is assumed to be a predeclared property
* The context object can be any model object, typically the object that is the context of the reference such as a property association
* @param context Element an AADL model element
* @param name property name possibly qualified with the property set name
* @return Property the property definition or null
*/
public Property findPropertyDefinition(EObject context, String name) {
// look for property type in property set
EReference reference = Aadl2Package.eINSTANCE.getPropertyAssociation_Property();
EObject e = findPropertySetElement(context, reference, name);
if (e != null && e instanceof Property) {
return (Property) e;
}
return null;
}
// /**
// * find property definition based on property name.
// * The name is qualified with the property set name, or if unqualified is assumed to be a predeclared property
// * @param name property name possibly qualified with the property set name
// * @return Property the property definition or null
// */
// public Property findPropertyDefinition(String name){
// // look for property type in property set
// EReference reference = Aadl2Package.eINSTANCE.getPropertyAssociation_Property();
// EObject e = findPropertySetElement(PredeclaredProperties.getAadlProjectPropertySet(), reference, name);
// if (e != null && e instanceof Property) {
// return (Property)e;
// }
// return null;
// }
//
public List<EObject> findPropertyDefinitionAsList(EObject context, EReference reference, String name) {
// look for property definition in property set
EObject e = findPropertySetElement(context, reference, name);
if (e != null && e instanceof Property) {
return Collections.singletonList(e);
}
return Collections.<EObject> emptyList();
}
/**
* Dependencies: PrototypeFormalReference, ClassifierReference,
* PrototypeOrClassifierReference, ComponentPrototypeClassifierReference,
* ComponentPrototypeRefinementReference. Based on the type of
* containingClassifier: ComponentTypeExtensionReference,
* ComponentImplementationExtensionReference, RealizationReference,
* FeatureGroupTypeExtendReference.
*/
/*
* TODO: Check for circular dependencies with prototypes. Example:
*
* abstract a prototypes p1: subprogram group; p2: subprogram group; end a;
*
* abstract implementation a.i ( p1 => p2, p2 => p1) subcomponents sub:
* subprogram group p1; calls sequence1: { call1: subprogram
* sub.access_feature_1; end a.i;
*
* This will cause a stack overflow!
*/
public static ComponentClassifier findClassifierForComponentPrototype(Classifier containingClassifier,
ComponentPrototype prototype) {
// TODO: Need to check that the prototype binding is a component
// prototype binding. In PrototypeFormalReference,
// we should check that component prototypes are bound by component
// prototype bindings.
ComponentPrototypeBinding binding = (ComponentPrototypeBinding) findPrototypeBinding(containingClassifier,
prototype);
if (binding != null && binding.getActuals().size() >= 1) {
SubcomponentType st = binding.getActuals().get(0).getSubcomponentType();
if (st instanceof ComponentClassifier) {
return (ComponentClassifier) st;
} else // It is a ComponentPrototypeReference
{
ComponentClassifier classifierForReferencedPrototype = findClassifierForComponentPrototype(
containingClassifier, (ComponentPrototype) st);
if (classifierForReferencedPrototype != null) {
return classifierForReferencedPrototype;
}
}
}
while (prototype.getConstrainingClassifier() == null && prototype.getRefined() != null) {
// TODO: Need to check that the component prototype refines a
// component prototype.
// This should be done in ComponentPrototypeRefinementReference.
prototype = (ComponentPrototype) prototype.getRefined();
}
if (prototype.getConstrainingClassifier() != null) {
return prototype.getConstrainingClassifier();
} else {
return null;
}
}
/**
* Dependencies: PrototypeFormalReference, ClassifierReference,
* PrototypeOrClassifierReference, ComponentPrototypeClassifierReference,
* ComponentPrototypeRefinementReference. Based on the type of
* classifierPrototypeContext: ComponentTypeExtensionReference,
* ComponentImplementationExtensionReference, RealizationReference,
* FeatureGroupTypeExtendReference.
*/
/*
* TODO: Check for circular dependencies with prototypes.
*/
public static ComponentClassifier findClassifierForComponentPrototype(Classifier classifierPrototypeContext,
Subcomponent subcomponentPrototypeContext, ComponentPrototype prototype) {
// TODO: Need to check that the prototype binding is a component
// prototype binding. In PrototypeFormalReference,
// we should check that component prototypes are bound by component
// prototype bindings.
ComponentPrototypeBinding binding = (ComponentPrototypeBinding) findPrototypeBinding(classifierPrototypeContext,
subcomponentPrototypeContext, prototype);
if (binding != null && binding.getActuals().size() >= 1) {
SubcomponentType st = binding.getActuals().get(0).getSubcomponentType();
if (st instanceof ComponentClassifier) {
return (ComponentClassifier) st;
} else if (st instanceof ComponentPrototype) {
ComponentClassifier classifierForReferencedPrototype = findClassifierForComponentPrototype(
classifierPrototypeContext, subcomponentPrototypeContext, ((ComponentPrototype) st));
if (classifierForReferencedPrototype != null) {
return classifierForReferencedPrototype;
}
}
}
while (prototype.getConstrainingClassifier() == null && prototype.getRefined() != null) {
// TODO: Need to check that the component prototype refines a
// component prototype.
// This should be done in ComponentPrototypeRefinementReference.
prototype = (ComponentPrototype) prototype.getRefined();
}
if (prototype.getConstrainingClassifier() != null) {
return prototype.getConstrainingClassifier();
} else {
return null;
}
}
/**
* Dependencies: PrototypeFormalReference, FeatureGroupTypeReference,
* PrototypeOrFeatureGroupTypeReference,
* FeatureGroupPrototypeClassifierReference,
* FeatureGroupPrototypeRefinementReference. Based on the type of
* containingClassifier: ComponentTypeExtensionReference,
* ComponentImplementationExtensionReference, RealizationReference,
* FeatureGroupTypeExtendReference.
*/
// TODO: Check for circular dependencies with prototypes.
public static FeatureGroupType findFeatureGroupTypeForFeatureGroupPrototype(Classifier containingClassifier,
FeatureGroupPrototype prototype) {
// TODO: Need to check that the prototype binding is a feature group
// prototype binding. In PrototypeFormalReference,
// we should check that feature group prototypes are bound by feature
// group prototype bindings.
FeatureGroupPrototypeBinding binding = (FeatureGroupPrototypeBinding) findPrototypeBinding(containingClassifier,
prototype);
if (binding != null) {
if (binding.getActual() instanceof FeatureGroupPrototypeActual) {
FeatureType ft = binding.getActual().getFeatureType();
if (ft instanceof FeatureGroupType) {
return (FeatureGroupType) ft;
} else {
FeatureGroupType featureGroupTypeForReferencedPrototype = findFeatureGroupTypeForFeatureGroupPrototype(
containingClassifier, ((FeatureGroupPrototype) ft));
if (featureGroupTypeForReferencedPrototype != null) {
return featureGroupTypeForReferencedPrototype;
}
}
}
}
if (prototype == null) {
return null;
}
while (prototype.getConstrainingFeatureGroupType() == null && prototype.getRefined() != null) {
// TODO: Need to check that the feature group prototype refines a
// feature group prototype.
// This should be done in FeatureGroupPrototypeRefinementReference.
prototype = (FeatureGroupPrototype) prototype.getRefined();
}
if (prototype.getConstrainingFeatureGroupType() != null) {
return prototype.getConstrainingFeatureGroupType();
} else {
return null;
}
}
/**
* Search for a {@link NamedElement} inside a package. If {@code context} is a
* {@link PublicPackageSection}, then this method will search through the
* {@link PublicPackageSection} only. If {@code context} is a
* {@link PrivatePackageSection}, then this method will search through the
* {@link PrivatePackageSection} and its corresponding
* {@link PublicPackageSection}.
* It will resolve any renames since it is a package internal lookup.
*
* Dependencies: RenamesAll, ComponentTypeRename, FeatureGroupTypeRename.
*
* @param name
* The name of the {@link NamedElement} to search for.
* @param context
* The {@link PackageSection} that contains the {@link Element}
* that needs the search result.
* @return The {@link NamedElement} or {@code null} if it cannot be found.
*/
public NamedElement findNamedElementInsideAadlPackage(String name, PackageSection context) {
NamedElement result = context.findInternallyVisibleNamedElement(name);
if (result == null && context instanceof PrivatePackageSection
&& ((AadlPackage) context.eContainer()).getOwnedPublicSection() != null) {
result = ((AadlPackage) context.eContainer()).getOwnedPublicSection()
.findInternallyVisibleNamedElement(name);
}
return result;
}
/**
* Search for a {@link NamedElement} with the name {@code elementName} in
* the containing package, which is also the specified by {@code packageName}.
* If the element cannot be found in the specified package, then {@code null} will be returned.
*
*
* @param packageName
* The name of the package that contains the element to search
* for, or null
* @param elementName
* The name of the element to search for.
* @param context
* The {@link PackageSection} that needs to refer to the
* specified {@link Element}.
* @return The {@link NamedElement} or {@code null} if it cannot be found.
*/
public NamedElement findNamedElementInAadlPackage(String packageName, String elementName, Namespace context) {
if (context instanceof PackageSection
&& (packageName == null || context.getName().equalsIgnoreCase(packageName))) {
// lookup in package that has reference
NamedElement ne = findNamedElementInsideAadlPackage(elementName, (PackageSection) context);
return ne;
} else {
// lookup in another package as external reference
// we need to do this because references that use package aliases did not get picked up
AadlPackage aadlPackage = null;
if (context instanceof PackageSection) {
aadlPackage = resolvePackageRename(packageName, (PackageSection) context);
if (aadlPackage == null) {
aadlPackage = AadlUtil.findImportedPackage(packageName, context);
}
}
if (aadlPackage != null && aadlPackage.getOwnedPublicSection() != null) {
return aadlPackage.getOwnedPublicSection().findNamedElement(elementName);
} else {
return null;
}
}
}
/**
* Find element in predeclared property sets which do not require the qualification
* @param propertyName
* @param context
* @param reference
* @return
*/
public EObject findNamedElementInPredeclaredPropertySets(String propertyName, EObject context,
EReference reference) {
for (String predeclaredPSName : AadlUtil.getPredeclaredPropertySetNames()) {
EObject res = getIndexedObject(context, reference, getQualifiedName(predeclaredPSName, propertyName));
if (res != null) {
return res;
}
}
return null;
}
public String getQualifiedName(String packageOrPropertySetName, String elementName) {
if (packageOrPropertySetName == null) {
return elementName;
} else {
return packageOrPropertySetName + "::" + elementName;
}
}
/**
* Dependencies: PrototypeFormalReference. Based on the type of classifier:
* ComponentTypeExtensionReference,
* ComponentImplementationExtensionReference, RealizationReference,
* FeatureGroupTypeExtendReference.
*/
public static PrototypeBinding findPrototypeBinding(Classifier classifier, Prototype prototype) {
for (PrototypeBinding binding : classifier.getOwnedPrototypeBindings()) {
if (binding.getFormal().equals(prototype)) {
return binding;
}
}
for (Generalization generalization : classifier.getGeneralizations()) {
PrototypeBinding result = findPrototypeBinding(generalization.getGeneral(), prototype);
if (result != null) {
return result;
}
}
return null;
}
/**
* Dependencies: PrototypeFormalReference. Based on the type of
* classifierPrototypeContext: ComponentTypeExtensionReference,
* ComponentImplementationExtensionReference, RealizationReference,
* FeatureGroupTypeExtendReference.
*/
public static PrototypeBinding findPrototypeBinding(Classifier classifierPrototypeContext,
Subcomponent subcomponentPrototypeContext, Prototype prototype) {
for (PrototypeBinding binding : subcomponentPrototypeContext.getOwnedPrototypeBindings()) {
if (binding.getFormal().equals(prototype)) {
return binding;
}
}
for (PrototypeBinding binding : classifierPrototypeContext.getOwnedPrototypeBindings()) {
if (binding.getFormal().equals(prototype)) {
return binding;
}
}
for (Generalization generalization : classifierPrototypeContext.getGeneralizations()) {
PrototypeBinding result = findPrototypeBinding(generalization.getGeneral(), prototype);
if (result != null) {
return result;
}
}
return null;
}
/**
* Dependencies: PrototypeFormalReference.
*/
public PrototypeBinding findPrototypeBinding(Subcomponent subcomponent, Prototype prototype) {
for (PrototypeBinding binding : subcomponent.getOwnedPrototypeBindings()) {
if (binding.getFormal().equals(prototype)) {
return binding;
}
}
return null;
}
public static EnumerationLiteral findEnumerationLiteral(Property property, String name) {
PropertyType propertyType = property.getPropertyType();
if (propertyType instanceof EnumerationType) {
return ((EnumerationType) propertyType).findLiteral(name);
}
return null;
}
public static UnitLiteral findUnitLiteral(Property property, String name) {
PropertyType propertyType = property.getPropertyType();
UnitsType unitsType = null;
if (propertyType instanceof NumberType) {
unitsType = ((NumberType) propertyType).getUnitsType();
} else if (propertyType instanceof RangeType) {
unitsType = ((RangeType) propertyType).getNumberType().getUnitsType();
}
if (unitsType != null) {
return unitsType.findLiteral(name);
}
return null;
}
public static UnitLiteral findUnitLiteral(NumberValue nv, String name) {
EReference reference = Aadl2Package.eINSTANCE.getNamedValue_NamedValue();
return findUnitLiteral(nv, reference, name);
}
public static List<EObject> findUnitLiteralAsList(EObject context, EReference reference, String name) {
EObject e = findUnitLiteral(context, reference, name);
if (e == null) {
return Collections.<EObject> emptyList();
}
return Collections.singletonList(e);
}
public static UnitLiteral findUnitLiteral(EObject context, EReference reference, String name) {
// look for unit literal pointed to by baseUnit
if (context instanceof UnitLiteral) {
UnitsType unitsType = (UnitsType) ((UnitLiteral) context).getOwner();
return (UnitLiteral) unitsType.findNamedElement(name);
} else if (context instanceof NumberValue) {
UnitsType unitsType = null;
NumberValue numberValue = (NumberValue) context;
Element owner = numberValue.getOwner();
while (owner instanceof ListValue) {
owner = owner.getOwner();
}
if (owner instanceof NumericRange) {
// values of a number
// property type.
unitsType = ((NumberType) owner.getOwner()).getUnitsType();
} else {
if (owner instanceof RangeValue) {
owner = owner.getOwner();
}
if (owner instanceof ListValue) {
owner = owner.getOwner();
}
PropertyType propertyType = null;
if (owner instanceof PropertyConstant) // Value of the
// property
// constant.
{
// TODO: Need to check that the type of the property
// constant is correct for the value.
// We should do this when the type of the constant is
// resolved in PropertyTypeReference.
propertyType = ((PropertyConstant) owner).getPropertyType();
} else if (owner instanceof Property) // Default value of a
// property
// definition.
{
// TODO: Need to check that the type of the property
// definition is correct for the value.
// We should do this when the type of the definition is
// resolved in PropertyValuePropertyTypeReference.
propertyType = ((Property) owner).getPropertyType();
} else if (owner instanceof ModalPropertyValue && owner.getOwner() instanceof PropertyAssociation)
// Value of an association.
{
// TODO: Need to check that the type of the property
// definition is correct for the value.
// We should do this when the definition of the
// association is resolved in
// PropertyDefinitionReference.
propertyType = ((PropertyAssociation) owner.getOwner()).getProperty().getPropertyType();
} else if (owner instanceof BasicPropertyAssociation)
// Inner value of a record value.
{
// TODO: Need to check that the type of the record field
// is correct for the value.
// We should do this when the record field of the record
// value is resolved in PropertyRecordFieldReference.
propertyType = ((BasicPropertyAssociation) owner).getProperty().getPropertyType();
}
propertyType = AadlUtil.getBasePropertyType(propertyType);
if (propertyType instanceof NumberType) {
unitsType = ((NumberType) propertyType).getUnitsType();
} else if (propertyType instanceof RangeType) {
RangeType rangeType = (RangeType) propertyType;
// The number type could be null if the model is incomplete.
if (rangeType.getNumberType() != null) {
unitsType = rangeType.getNumberType().getUnitsType();
}
}
}
if (unitsType != null) {
return unitsType.findLiteral(name);
}
}
return null;
}
public static EnumerationLiteral findEnumerationLiteral(EnumerationType enumType, String name) {
return enumType.findLiteral(name);
}
public static EnumerationLiteral findEnumerationLiteral(NamedValue nv, String name) {
EReference reference = Aadl2Package.eINSTANCE.getNamedValue_NamedValue();
List<EObject> el = findEnumLiteralAsList(nv, reference, name);
if (!el.isEmpty() && el.get(0) instanceof EnumerationLiteral) {
return (EnumerationLiteral) el.get(0);
}
return null;
}
public static List<EObject> findEnumLiteralAsList(EObject context, EReference reference, String name) {
// look for enumeration literal
if (context instanceof NamedValue) {
NamedValue value = (NamedValue) context;
EObject owner = value.getOwner();
while (owner instanceof ListValue) {
owner = owner.eContainer();
}
PropertyType propertyType = null;
if (owner instanceof PropertyConstant) // Value of the property
// constant.
{
// TODO: Need to check that the type of the property
// constant is correct for the value.
// We should do this when the type of the constant is
// resolved in PropertyTypeReference.
propertyType = ((PropertyConstant) owner).getPropertyType();
} else if (owner instanceof Property) // Default value of a
// property definition.
{
// TODO: Need to check that the type of the property
// definition is correct for the value.
// We should do this when the type of the definition is
// resolved in PropertyValuePropertyTypeReference.
propertyType = ((Property) owner).getPropertyType();
} else if (owner instanceof ModalPropertyValue && owner.eContainer() instanceof PropertyAssociation) // Value
// of
// an
// association.
{
// TODO: Need to check that the type of the property
// definition is correct for the value.
// We should do this when the definition of the association
// is resolved in PropertyDefinitionReference.
Property p = ((PropertyAssociation) owner.eContainer()).getProperty();
propertyType = p.getPropertyType();
} else if (owner instanceof BasicPropertyAssociation) // Inner
// value
// of a
// record
// value.
{
// TODO: Need to check that the type of the record field is
// correct for the value.
// We should do this when the record field of the record
// value is resolved in PropertyRecordFieldReference.
propertyType = ((BasicPropertyAssociation) owner).getProperty().getPropertyType();
}
propertyType = AadlUtil.getBasePropertyType(propertyType);
if (propertyType != null && propertyType instanceof EnumerationType) {
EnumerationLiteral literal = ((EnumerationType) propertyType).findLiteral(name);
if (literal != null) {
return Collections.singletonList((EObject) literal);
}
}
}
return Collections.<EObject> emptyList();
}
protected static <T> T findElementInContext(Element referencingObject, Context context, String name,
Class<T> validSearchResultType) {
NamedElement searchResult = null;
if (context == null) {
searchResult = AadlUtil.getContainingClassifier(referencingObject).findNamedElement(name);
} else if (context instanceof FeatureGroup) {
FeatureGroup featureGroup = (FeatureGroup) context;
while (featureGroup.getFeatureGroupType() == null && featureGroup.getFeatureGroupPrototype() == null
&& featureGroup.getRefined() instanceof FeatureGroup) {
featureGroup = (FeatureGroup) featureGroup.getRefined();
}
FeatureGroupType featureGroupType = null;
if (featureGroup.getFeatureGroupType() != null) {
featureGroupType = featureGroup.getFeatureGroupType();
} else if (featureGroup.getFeatureGroupPrototype() != null) {
featureGroupType = findFeatureGroupTypeForFeatureGroupPrototype(
AadlUtil.getContainingClassifier(referencingObject), featureGroup.getFeatureGroupPrototype());
}
if (featureGroupType != null) {
searchResult = featureGroupType.findNamedElement(name);
}
} else if (context instanceof Feature) {
Feature feature = (Feature) context;
while (feature.getClassifier() == null && feature.getPrototype() == null && feature.getRefined() != null) {
feature = feature.getRefined();
}
Classifier featureClassifier = null;
if (feature.getClassifier() != null) {
featureClassifier = feature.getClassifier();
} else if (feature.getPrototype() != null) {
featureClassifier = findClassifierForComponentPrototype(
AadlUtil.getContainingClassifier(referencingObject), feature.getPrototype());
}
if (featureClassifier != null) {
searchResult = featureClassifier.findNamedElement(name);
}
} else if (context instanceof Subcomponent) {
Subcomponent subcomponent = (Subcomponent) context;
while (subcomponent.getSubcomponentType() == null && subcomponent.getRefined() != null) {
subcomponent = subcomponent.getRefined();
}
ComponentClassifier subcomponentClassifier = null;
if (subcomponent.getSubcomponentType() instanceof ComponentClassifier) {
subcomponentClassifier = (ComponentClassifier) subcomponent.getSubcomponentType();
} else if (subcomponent.getSubcomponentType() instanceof ComponentPrototype) {
subcomponentClassifier = findClassifierForComponentPrototype(
AadlUtil.getContainingClassifier(referencingObject),
(ComponentPrototype) subcomponent.getSubcomponentType());
}
if (subcomponentClassifier != null) {
searchResult = subcomponentClassifier.findNamedElement(name);
}
} else if (context instanceof SubprogramCall) {
SubprogramCall subprogramCall = (SubprogramCall) context;
if (subprogramCall.getCalledSubprogram() instanceof ComponentClassifier) {
searchResult = ((ComponentClassifier) subprogramCall.getCalledSubprogram()).findNamedElement(name);
} else if (subprogramCall.getCalledSubprogram() instanceof SubprogramSubcomponent) {
Subcomponent subcomponent = (SubprogramSubcomponent) subprogramCall.getCalledSubprogram();
while (subcomponent.getSubcomponentType() == null && subcomponent.getRefined() != null) {
subcomponent = subcomponent.getRefined();
}
ComponentClassifier subcomponentClassifier = null;
if (subcomponent.getSubcomponentType() instanceof ComponentClassifier) {
subcomponentClassifier = (ComponentClassifier) subcomponent.getSubcomponentType();
} else if (subcomponent.getSubcomponentType() instanceof ComponentPrototype) {
subcomponentClassifier = findClassifierForComponentPrototype(
AadlUtil.getContainingClassifier(referencingObject),
(ComponentPrototype) subcomponent.getSubcomponentType());
}
if (subcomponentClassifier != null) {
searchResult = subcomponentClassifier.findNamedElement(name);
}
} else if (subprogramCall.getCalledSubprogram() instanceof SubprogramAccess) {
Feature access = (SubprogramAccess) subprogramCall.getCalledSubprogram();
while (access.getClassifier() == null && access.getPrototype() == null && access.getRefined() != null) {
access = access.getRefined();
}
Classifier accessClassifier = null;
if (access.getClassifier() != null) {
accessClassifier = access.getClassifier();
} else if (access.getPrototype() != null) {
CallContext callContext = subprogramCall.getContext();
if (callContext instanceof ComponentType) {
accessClassifier = findClassifierForComponentPrototype((ComponentType) callContext,
access.getPrototype());
} else if (callContext instanceof FeatureGroup) {
FeatureGroup callContextFeatureGroup = (FeatureGroup) callContext;
FeatureGroupType prototypeContext = null;
while (callContextFeatureGroup.getFeatureGroupType() == null
&& callContextFeatureGroup.getFeatureGroupPrototype() == null
&& callContextFeatureGroup.getRefined() instanceof FeatureGroup) {
callContextFeatureGroup = (FeatureGroup) callContextFeatureGroup.getRefined();
}
if (callContextFeatureGroup.getFeatureGroupType() != null) {
prototypeContext = callContextFeatureGroup.getFeatureGroupType();
} else if (callContextFeatureGroup.getFeatureGroupPrototype() != null) {
prototypeContext = findFeatureGroupTypeForFeatureGroupPrototype(
AadlUtil.getContainingClassifier(referencingObject),
callContextFeatureGroup.getFeatureGroupPrototype());
}
if (prototypeContext != null) {
accessClassifier = findClassifierForComponentPrototype(prototypeContext,
access.getPrototype());
}
} else if (callContext instanceof SubprogramGroupAccess) {
Feature callContextAccess = (SubprogramGroupAccess) callContext;
Classifier prototypeContext = null;
while (callContextAccess.getClassifier() == null && callContextAccess.getPrototype() == null
&& callContextAccess.getRefined() != null) {
callContextAccess = callContextAccess.getRefined();
}
if (callContextAccess.getClassifier() != null) {
prototypeContext = callContextAccess.getClassifier();
} else if (callContextAccess.getPrototype() != null) {
prototypeContext = findClassifierForComponentPrototype(
AadlUtil.getContainingClassifier(referencingObject),
callContextAccess.getPrototype());
}
if (prototypeContext != null) {
accessClassifier = findClassifierForComponentPrototype(prototypeContext,
access.getPrototype());
}
} else if (callContext instanceof SubprogramGroupSubcomponent) {
Subcomponent callContextSubcomponent = (SubprogramGroupSubcomponent) callContext;
while (callContextSubcomponent.getSubcomponentType() == null
&& callContextSubcomponent.getRefined() != null) {
callContextSubcomponent = callContextSubcomponent.getRefined();
}
if (callContextSubcomponent.getSubcomponentType() instanceof ComponentClassifier) {
if (callContextSubcomponent.getOwnedPrototypeBindings().isEmpty()) {
accessClassifier = findClassifierForComponentPrototype(
callContextSubcomponent.getClassifier(), access.getPrototype());
} else {
accessClassifier = findClassifierForComponentPrototype(
callContextSubcomponent.getClassifier(), callContextSubcomponent,
access.getPrototype());
}
} else if (callContextSubcomponent.getSubcomponentType() instanceof ComponentPrototype) {
ComponentClassifier prototypeContext = findClassifierForComponentPrototype(
AadlUtil.getContainingClassifier(referencingObject),
callContextSubcomponent.getPrototype());
if (prototypeContext != null) {
accessClassifier = findClassifierForComponentPrototype(prototypeContext,
access.getPrototype());
}
}
} else // callContext is null.
{
accessClassifier = findClassifierForComponentPrototype(
AadlUtil.getContainingClassifier(referencingObject), access.getPrototype());
}
}
if (accessClassifier != null) {
searchResult = accessClassifier.findNamedElement(name);
}
} else if (subprogramCall.getCalledSubprogram() instanceof ComponentPrototype) {
ComponentClassifier classifier = findClassifierForComponentPrototype(
AadlUtil.getContainingClassifier(referencingObject),
(ComponentPrototype) subprogramCall.getCalledSubprogram());
if (classifier != null) {
searchResult = classifier.findNamedElement(name);
}
}
}
if (validSearchResultType.isInstance(searchResult)) {
return validSearchResultType.cast(searchResult);
} else {
return null;
}
}
}