Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,10 @@ private List<Resource> getCandidateResources(ResourceSet resourceSet) {
*/
private Element getElement(Resource resource, String[] segments) {
for (EObject object : resource.getContents()) {
if (object instanceof Element element) {
Element match = resolveElement(element, segments, 0);
// Element not contained in a Namespace can not be access using their qualified names
// Section 8.3.2.1.2 Element: "If this Element does not have an owningNamespace, then its qualifiedName is null.”
if (object instanceof Namespace namespace) {
Element match = resolveElement(namespace, segments, 0);
if (match != null) {
return match;
}
Expand All @@ -115,53 +117,30 @@ private Element getElement(Resource resource, String[] segments) {
* Resolves one qualified-name segment at a time by matching the current
* element and then descending through namespace memberships.
*/
private Element resolveElement(Element element, String[] segments, int index) {
if (!matchesElementName(element, segments[index])) {
private Element resolveElement(Namespace namespace, String[] segments, int index) {
if (namespace == null || index >= segments.length) {
return null;
}

if (index == segments.length - 1) {
return element;
}

if (!(element instanceof Namespace namespace)) {
return null;
}

String nextSegment = segments[index + 1];
for (Membership membership : getOwnedMemberships(namespace)) {
String currentSegment = segments[index];
for (Membership membership : namespace.getOwnedMembership()) {
Element member = membership.getMemberElement();
if (member == null || !matchesMembershipName(membership, member, nextSegment)) {
continue;
}

if (index + 1 == segments.length - 1) {
return member;
}

Element nested = resolveElement(member, segments, index + 1);
if (nested != null) {
return nested;
if (member != null && matchesMembershipName(membership, member, currentSegment)) {
if (index == segments.length - 1) {
return member;
} else if (member instanceof Namespace namespaceMember) {
Element nested = resolveElement(namespaceMember, segments, index + 1);
if (nested != null) {
return nested;
}
}
}
}

return null;
}

/**
* Returns the memberships owned directly by a namespace using only EMF model
* state, avoiding any Xtext-specific scoping infrastructure.
*/
private List<Membership> getOwnedMemberships(Namespace namespace) {
List<Membership> memberships = new ArrayList<>();
for (EObject relationship : namespace.getOwnedRelationship()) {
if (relationship instanceof Membership membership) {
memberships.add(membership);
}
}
return memberships;
}

/**
* Matches a qualified-name segment against an element's declared name or
* declared short name.
Expand Down Expand Up @@ -193,6 +172,6 @@ private boolean matchesMembershipName(Membership membership, Element member, Str
* Performs an exact name comparison while tolerating missing values.
*/
private boolean matches(String expected, String actual) {
return expected != null && actual != null && expected.equals(actual);
return expected != null && expected.equals(actual);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,22 @@
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.junit.Test;
import org.omg.sysml.lang.sysml.Namespace;
import org.omg.sysml.lang.sysml.OwningMembership;
import org.omg.sysml.lang.sysml.SysMLFactory;
import org.omg.sysml.lang.sysml.SysMLPackage;
import org.omg.sysml.lang.sysml.Type;
import org.omg.sysml.util.NamespaceUtil;
import org.omg.sysml.util.SysMLLibraryUtil;

/**
* Verifies the plain-EMF standalone bootstrap for {@link SysMLLogicStandaloneSetup}.
* Verifies the plain-EMF standalone bootstrap for
* {@link SysMLLogicStandaloneSetup}.
*/
public class SysMLLogicStandaloneSetupTest {

/**
* Checks that the standalone setup installs library lookup and delegate
* support without requiring any Xtext runtime bootstrap, and that invoking
* the setup multiple times remains safe for subsequent lookups.
* Checks that the standalone setup installs library lookup and delegate support
* without requiring any Xtext runtime bootstrap, and that invoking the setup
* multiple times remains safe for subsequent lookups.
*/
@Test
public void standaloneSetupResolvesLibraryElementsWithoutXtext() {
Expand All @@ -59,21 +60,23 @@ public void standaloneSetupResolvesLibraryElementsWithoutXtext() {
resourceSet.getResources().add(libraryResource);
resourceSet.getResources().add(modelResource);

SysMLFactory factory = SysMLFactory.eINSTANCE;
Namespace libraryRootNamespace = SysMLFactory.eINSTANCE.createNamespace();
libraryResource.getContents().add(libraryRootNamespace);

Namespace library = factory.createNamespace();
Namespace library = SysMLFactory.eINSTANCE.createNamespace();
library.setDeclaredName("Base");
libraryResource.getContents().add(library);
NamespaceUtil.addOwnedMemberTo(libraryRootNamespace,library);

Type anything = factory.createType();
Type anything = SysMLFactory.eINSTANCE.createType();
anything.setDeclaredName("Anything");
OwningMembership anythingMembership = factory.createOwningMembership();
anythingMembership.setOwnedMemberElement(anything);
library.getOwnedRelationship().add(anythingMembership);
NamespaceUtil.addOwnedMemberTo(library, anything);

Namespace context = factory.createNamespace();
Namespace modelRootNamespace = SysMLFactory.eINSTANCE.createNamespace();
modelResource.getContents().add(modelRootNamespace);

Namespace context = SysMLFactory.eINSTANCE.createNamespace();
context.setDeclaredName("UserModel");
modelResource.getContents().add(context);
NamespaceUtil.addOwnedMemberTo(modelRootNamespace, context);

assertEquals("Anything", anything.effectiveName());
assertEquals("Anything", anything.getName());
Expand Down
Loading