Skip to content

Commit

Permalink
Fix default endpoint resolve strategy from client lib not conforming …
Browse files Browse the repository at this point in the history
…with specification (#504)

* test: add bug failing test

* fix: change endpoint parsing mechanism of the Aas/Sm DescriptorResolvers to conform with spec

* ci: retriggering

* fix: address review remarks
  • Loading branch information
mateusmolina-iese authored Oct 28, 2024
1 parent cebe8f0 commit 31ac86c
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,20 @@

import org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor;
import org.eclipse.digitaltwin.basyx.aasregistry.client.model.Endpoint;
import org.eclipse.digitaltwin.basyx.aasregistry.client.model.ProtocolInformation;
import org.eclipse.digitaltwin.basyx.aasservice.client.ConnectedAasService;
import org.eclipse.digitaltwin.basyx.client.internal.resolver.DescriptorResolver;

/**
* Resolves an AasDescriptor into a {@link ConnectedAasService}
*
*
* @author mateusmolina, danish
*
*/
public class AasDescriptorResolver implements DescriptorResolver<AssetAdministrationShellDescriptor, ConnectedAasService> {

static final String SPEC_INTERFACE = "AAS-3.0";

private final EndpointResolver endpointResolver;

/**
Expand All @@ -66,16 +69,7 @@ public ConnectedAasService resolveDescriptor(AssetAdministrationShellDescriptor

public static Optional<URI> parseEndpoint(Endpoint endpoint) {
try {
if (endpoint == null || endpoint.getProtocolInformation() == null || endpoint.getProtocolInformation()
.getHref() == null)
return Optional.empty();

String baseHref = endpoint.getProtocolInformation()
.getHref();
// TODO not working: String queryString = "?" + endpoint.toUrlQueryString();
String queryString = "";
URI uri = new URI(baseHref + queryString);
return Optional.of(uri);
return Optional.ofNullable(endpoint).filter(ep -> ep.getInterface().equals(SPEC_INTERFACE)).map(Endpoint::getProtocolInformation).map(ProtocolInformation::getHref).map(URI::create);
} catch (Exception e) {
return Optional.empty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

package org.eclipse.digitaltwin.basyx.aasenvironment.client.resolvers;

import org.eclipse.digitaltwin.basyx.submodelregistry.client.model.ProtocolInformation;
import org.eclipse.digitaltwin.basyx.client.internal.resolver.DescriptorResolver;
import java.net.URI;
import java.util.Optional;
Expand All @@ -41,6 +42,8 @@
*/
public class SubmodelDescriptorResolver implements DescriptorResolver<SubmodelDescriptor, ConnectedSubmodelService> {

static final String SPEC_INTERFACE = "SUBMODEL-3.0";

private final EndpointResolver endpointResolver;

/**
Expand All @@ -67,16 +70,7 @@ public ConnectedSubmodelService resolveDescriptor(SubmodelDescriptor smDescripto

public static Optional<URI> parseEndpoint(Endpoint endpoint) {
try {
if (endpoint == null || endpoint.getProtocolInformation() == null || endpoint.getProtocolInformation()
.getHref() == null)
return Optional.empty();

String baseHref = endpoint.getProtocolInformation()
.getHref();
// TODO not working: String queryString = "?" + endpoint.toUrlQueryString();
String queryString = "";
URI uri = new URI(baseHref + queryString);
return Optional.of(uri);
return Optional.ofNullable(endpoint).filter(ep -> ep.getInterface().equals(SPEC_INTERFACE)).map(Endpoint::getProtocolInformation).map(ProtocolInformation::getHref).map(URI::create);
} catch (Exception e) {
return Optional.empty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

package org.eclipse.digitaltwin.basyx.aasenvironment.client;

import java.util.LinkedList;

import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell;
import org.eclipse.digitaltwin.aas4j.v3.model.AssetInformation;
import org.eclipse.digitaltwin.aas4j.v3.model.AssetKind;
Expand All @@ -38,6 +40,7 @@
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultReference;
import org.eclipse.digitaltwin.aas4j.v3.model.impl.DefaultSubmodel;
import org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor;
import org.eclipse.digitaltwin.basyx.aasregistry.client.model.Endpoint;
import org.eclipse.digitaltwin.basyx.aasregistry.main.client.mapper.DummyAasDescriptorFactory;
import org.eclipse.digitaltwin.basyx.http.Base64UrlEncoder;
import org.eclipse.digitaltwin.basyx.submodelregistry.client.mapper.AttributeMapper;
Expand Down Expand Up @@ -91,6 +94,15 @@ public AssetAdministrationShellDescriptor buildAasPre1Descriptor() {
return DummyAasDescriptorFactory.createDummyDescriptor(AAS_PRE1_ID, AAS_PRE1_IDSHORT, AAS_PRE1_GLOBALASSETID, aasRepositoryBasePath);
}

public AssetAdministrationShellDescriptor buildAasPre1Descriptor_withMultipleInterfaces() {
LinkedList<Endpoint> endpoints = new LinkedList<>();

endpoints.add(DummyAasDescriptorFactory.createEndpoint(aasRepositoryBasePath, "AAS-REPOSITORY-3.0"));
endpoints.add(DummyAasDescriptorFactory.createEndpoint(AAS_PRE1_ID, aasRepositoryBasePath, "AAS-3.0"));

return DummyAasDescriptorFactory.createDummyDescriptor(AAS_PRE1_ID, AAS_PRE1_IDSHORT, AAS_PRE1_GLOBALASSETID, endpoints);
}

public Reference buildSmPre1Ref() {
return new DefaultReference.Builder().type(ReferenceTypes.MODEL_REFERENCE).keys(new DefaultKey.Builder().type(KeyTypes.SUBMODEL).value(SM_PRE1_ID).build()).build();
}
Expand All @@ -100,7 +112,16 @@ public Submodel buildSmPre1() {
}

public SubmodelDescriptor buildSmPre1Descriptor() {
return DummySubmodelDescriptorFactory.createDummyDescriptor(SM_PRE1_ID, SM_PRE1_IDSHORT, smRepositoryBasePath, null);
return DummySubmodelDescriptorFactory.createDummyDescriptor(SM_PRE1_ID, SM_PRE1_IDSHORT, null, smRepositoryBasePath);
}

public SubmodelDescriptor buildSmPre1Descriptor_withMultipleInterfaces() {
LinkedList<org.eclipse.digitaltwin.basyx.submodelregistry.client.model.Endpoint> endpoints = new LinkedList<>();

endpoints.add(DummySubmodelDescriptorFactory.createEndpoint(smRepositoryBasePath, "SUBMODEL-REPOSITORY-3.0"));
endpoints.add(DummySubmodelDescriptorFactory.createEndpoint(SM_PRE1_ID, smRepositoryBasePath, "SUBMODEL-3.0"));

return DummySubmodelDescriptorFactory.createDummyDescriptor(SM_PRE1_ID, SM_PRE1_IDSHORT, null, endpoints);
}

public AssetAdministrationShell buildAasPos1() {
Expand All @@ -116,7 +137,7 @@ public AssetAdministrationShellDescriptor buildAasPos1Descriptor() {
}

public SubmodelDescriptor buildSmPos1Descriptor() {
return DummySubmodelDescriptorFactory.createDummyDescriptor(SM_POS1_ID, SM_POS1_IDSHORT, smRepositoryBasePath, new AttributeMapper(ConnectedAasManagerHelper.buildObjectMapper()).mapSemanticId(buildSmPos1SemanticId()));
return DummySubmodelDescriptorFactory.createDummyDescriptor(SM_POS1_ID, SM_POS1_IDSHORT, new AttributeMapper(ConnectedAasManagerHelper.buildObjectMapper()).mapSemanticId(buildSmPos1SemanticId()), smRepositoryBasePath);
}

public Reference buildSmPos1SemanticId() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import org.eclipse.digitaltwin.aas4j.v3.model.Submodel;
import org.eclipse.digitaltwin.basyx.aasenvironment.client.DummyAasEnvironmentComponent;
import org.eclipse.digitaltwin.basyx.aasenvironment.client.TestFixture;
import org.eclipse.digitaltwin.basyx.aasregistry.client.ApiException;
import org.eclipse.digitaltwin.basyx.aasrepository.AasRepository;
import org.eclipse.digitaltwin.basyx.submodelrepository.SubmodelRepository;
import org.junit.AfterClass;
Expand All @@ -52,10 +51,10 @@ public class RegistryDescriptorResolverTest {
private static AasRepository aasRepository;
private static SubmodelRepository smRepository;

private final static String AAS_REPOSITORY_BASE_PATH = "http://localhost:8081";
private final static String SM_REPOSITORY_BASE_PATH = "http://localhost:8081";
private static final String AAS_REPOSITORY_BASE_PATH = "http://localhost:8081";
private static final String SM_REPOSITORY_BASE_PATH = "http://localhost:8081";

private final static TestFixture FIXTURE = new TestFixture(AAS_REPOSITORY_BASE_PATH, SM_REPOSITORY_BASE_PATH);
private static final TestFixture FIXTURE = new TestFixture(AAS_REPOSITORY_BASE_PATH, SM_REPOSITORY_BASE_PATH);

@BeforeClass
public static void initApplication() {
Expand All @@ -73,7 +72,7 @@ public static void cleanUp() {
}

@Test
public void resolveAasDescriptor() throws ApiException {
public void resolveAasDescriptor() {
AasDescriptorResolver resolver = new AasDescriptorResolver(new EndpointResolver());

AssetAdministrationShell expectedAas = FIXTURE.buildAasPre1();
Expand All @@ -84,7 +83,18 @@ public void resolveAasDescriptor() throws ApiException {
}

@Test
public void resolveSmDescriptor() throws ApiException {
public void resolveAasDescriptor_withMultipleInterfaces() {
AasDescriptorResolver resolver = new AasDescriptorResolver(new EndpointResolver());

AssetAdministrationShell expectedAas = FIXTURE.buildAasPre1();

AssetAdministrationShell actualAas = resolver.resolveDescriptor(FIXTURE.buildAasPre1Descriptor_withMultipleInterfaces()).getAAS();

assertEquals(expectedAas, actualAas);
}

@Test
public void resolveSmDescriptor() {
SubmodelDescriptorResolver resolver = new SubmodelDescriptorResolver(new EndpointResolver());

Submodel expectedSm = FIXTURE.buildSmPre1();
Expand All @@ -94,4 +104,14 @@ public void resolveSmDescriptor() throws ApiException {
assertEquals(expectedSm, actualSm);
}

@Test
public void resolveSmDescriptor_withMultipleInterfaces() {
SubmodelDescriptorResolver resolver = new SubmodelDescriptorResolver(new EndpointResolver());

Submodel expectedSm = FIXTURE.buildSmPre1();

Submodel actualSm = resolver.resolveDescriptor(FIXTURE.buildSmPre1Descriptor_withMultipleInterfaces()).getSubmodel();

assertEquals(expectedSm, actualSm);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetAdministrationShellDescriptor;
import org.eclipse.digitaltwin.basyx.aasregistry.client.model.AssetKind;
Expand All @@ -43,31 +45,44 @@
public class DummyAasDescriptorFactory {
private static final String AAS_REPOSITORY_PATH = "/shells";

public static AssetAdministrationShellDescriptor createDummyDescriptor(String aasId, String idShort, String globalAssetId, String... aasRepoBaseUrls) {
public static AssetAdministrationShellDescriptor createDummyDescriptor(String aasId, String idShort, String globalAssetId, List<Endpoint> endpoints) {

AssetAdministrationShellDescriptor descriptor = new AssetAdministrationShellDescriptor();

descriptor.setId(aasId);
descriptor.setIdShort(idShort);
descriptor.setAssetKind(AssetKind.INSTANCE);
descriptor.setGlobalAssetId(globalAssetId);
descriptor.setEndpoints(endpoints);

return descriptor;
}

public static AssetAdministrationShellDescriptor createDummyDescriptor(String aasId, String idShort, String globalAssetId, String... aasRepoBaseUrls) {
LinkedList<Endpoint> endpoints = new LinkedList<>();

for (String eachUrl : aasRepoBaseUrls) {
descriptor.addEndpointsItem(createEndpointItem(aasId, eachUrl));
endpoints.add(createEndpoint(aasId, eachUrl, "AAS-3.0"));
}
return descriptor;

return createDummyDescriptor(aasId, idShort, globalAssetId, endpoints);
}

private static Endpoint createEndpointItem(String aasId, String aasRepoBaseUrl) {
public static Endpoint createEndpoint(String endpointUrl, String endpointInterface) {
Endpoint endpoint = new Endpoint();
endpoint.setInterface("AAS-3.0");
endpoint.setProtocolInformation(createProtocolInformation(aasId, aasRepoBaseUrl));
endpoint.setInterface(endpointInterface);
endpoint.setProtocolInformation(createProtocolInformation(endpointUrl));

return endpoint;
}

private static ProtocolInformation createProtocolInformation(String aasId, String aasRepoBaseUrl) {
public static Endpoint createEndpoint(String aasId, String aasRepoBaseUrl, String endpointInterface) {
String href = createHref(aasId, aasRepoBaseUrl);

return createEndpoint(href, endpointInterface);
}

private static ProtocolInformation createProtocolInformation(String href) {
ProtocolInformation protocolInformation = new ProtocolInformation();
protocolInformation.setHref(href);
protocolInformation.endpointProtocol(getProtocol(href));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.digitaltwin.basyx.http.Base64UrlEncodedIdentifier;
import org.eclipse.digitaltwin.basyx.submodelregistry.client.model.Endpoint;
Expand All @@ -47,37 +49,45 @@
public class DummySubmodelDescriptorFactory {
private static final String SUBMODEL_REPOSITORY_PATH = "/submodels";

public static SubmodelDescriptor createDummyDescriptor(String smId, String idShort, String smRepoBaseUrl, Reference semanticId) {
return createDummyDescriptor(smId, idShort, new String[] {smRepoBaseUrl}, semanticId);
}

public static SubmodelDescriptor createDummyDescriptor(String smId, String idShort, String[] smRepoBaseUrls, Reference semanticId) {
public static SubmodelDescriptor createDummyDescriptor(String smId, String idShort, Reference semanticId, List<Endpoint> endpoints) {
SubmodelDescriptor descriptor = new SubmodelDescriptor();

descriptor.setId(smId);
descriptor.setIdShort(idShort);
descriptor.setSemanticId(semanticId);
descriptor.setEndpoints(endpoints);

return descriptor;
}

public static SubmodelDescriptor createDummyDescriptor(String smId, String idShort, Reference semanticId, String... smRepoBaseUrls) {
LinkedList<Endpoint> endpoints = new LinkedList<>();
for (String eachUrl : smRepoBaseUrls) {
descriptor.addEndpointsItem(createEndpointItem(smId, eachUrl));
endpoints.add(createEndpoint(smId, eachUrl, "SUBMODEL-3.0"));
}
return descriptor;

return createDummyDescriptor(smId, idShort, semanticId, endpoints);
}

public static Reference createSemanticId() {
return new Reference().keys(Arrays.asList(new Key().type(KeyTypes.GLOBALREFERENCE).value("0173-1#01-AFZ615#016"))).type(ReferenceTypes.EXTERNALREFERENCE);
}

private static Endpoint createEndpointItem(String smId, String smRepoBaseUrl) {
public static Endpoint createEndpoint(String endpointUrl, String endpointInterface) {
Endpoint endpoint = new Endpoint();
endpoint.setInterface("SUBMODEL-3.0");
endpoint.setProtocolInformation(createProtocolInformation(smId, smRepoBaseUrl));
endpoint.setInterface(endpointInterface);
endpoint.setProtocolInformation(createProtocolInformation(endpointUrl));

return endpoint;
}

private static ProtocolInformation createProtocolInformation(String smId, String smRepoBaseUrl) {
public static Endpoint createEndpoint(String smId, String smRepoBaseUrl, String endpointInterface) {
String href = createHref(smId, smRepoBaseUrl);

return createEndpoint(href, endpointInterface);
}

private static ProtocolInformation createProtocolInformation(String href) {
ProtocolInformation protocolInformation = new ProtocolInformation();
protocolInformation.setHref(href);
protocolInformation.endpointProtocol(getProtocol(href));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public abstract class SubmodelRepositoryRegistryLinkTestSuite {
protected abstract String getSubmodelRegistryUrl();
protected abstract SubmodelRegistryApi getSubmodelRegistryApi();

private final SubmodelDescriptor DUMMY_DESCRIPTOR = DummySubmodelDescriptorFactory.createDummyDescriptor(DUMMY_SUBMODEL_ID, DUMMY_SUBMODEL_IDSHORT, getSubmodelRepoBaseUrls(), DummySubmodelDescriptorFactory.createSemanticId());
private final SubmodelDescriptor DUMMY_DESCRIPTOR = DummySubmodelDescriptorFactory.createDummyDescriptor(DUMMY_SUBMODEL_ID, DUMMY_SUBMODEL_IDSHORT, DummySubmodelDescriptorFactory.createSemanticId(), getSubmodelRepoBaseUrls());

@Test
public void createSubmodel() throws FileNotFoundException, IOException, ApiException {
Expand Down

0 comments on commit 31ac86c

Please sign in to comment.