Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
78d2bde
deps: update aas4j to 2.0.1
carlos-schmidt May 4, 2026
4b3edf8
fix: minor issues
carlos-schmidt May 4, 2026
ccbdcbc
fix: SML.orderRelevant default to false
carlos-schmidt May 4, 2026
443d2ac
feat: update aas versions
carlos-schmidt May 4, 2026
638a58d
feat: more aas versions
carlos-schmidt May 4, 2026
2a811fc
fix: sonar
carlos-schmidt May 5, 2026
b8dc30a
docs: changelog + readme updates
carlos-schmidt May 5, 2026
e003f67
feat: update default api prefix
carlos-schmidt May 13, 2026
bd7496b
feat: SearchAllAssetAdministrationShellIdsByAssetLink
carlos-schmidt May 13, 2026
4fb22e0
chore: mark APIv3.0 function as deprecated
carlos-schmidt May 13, 2026
dac7a89
feat: add SearchAllAssetAdministrationShellIdsByAssetLinkRequestHandler
carlos-schmidt May 13, 2026
38fb2bd
feat: remove duplicate request handling logic
carlos-schmidt May 13, 2026
a4bd345
fix: spotless
carlos-schmidt May 13, 2026
f40e8b6
fix: small fixes
carlos-schmidt May 18, 2026
d74af4f
fix: more updates to 3.1
carlos-schmidt May 18, 2026
34d77b8
fix: release notes default api prefix
carlos-schmidt May 18, 2026
1f22097
fix: deprecated description, stream tolist
carlos-schmidt May 19, 2026
8e026ae
Merge remote-tracking branch 'origin' into deps/update-aas4j
carlos-schmidt May 21, 2026
542bfc2
Merge remote-tracking branch 'origin' into deps/update-aas4j
carlos-schmidt May 21, 2026
ddcc1ff
fix: revert proxy to Search...Handler
carlos-schmidt May 21, 2026
5232493
fix: spotless
carlos-schmidt May 21, 2026
93ad772
fix: re-add update from aas4j v2
carlos-schmidt May 21, 2026
12676a8
Merge branch 'main' into deps/update-aas4j
carlos-schmidt May 28, 2026
5443316
Merge remote-tracking branch 'remotes/origin/main' into deps/update-a…
tbischoff2 Jun 1, 2026
9b1b85c
Merge remote-tracking branch 'remotes/origin/main' into deps/update-a…
tbischoff2 Jun 3, 2026
94c0b87
fix: review comments
carlos-schmidt Jun 8, 2026
a150bc3
Merge branch 'main' into deps/update-aas4j
mjacoby Jun 9, 2026
57c666b
improve formatting
mjacoby Jun 9, 2026
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
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ The features of FA³ST Service include


> [!TIP]
> For more details on FA³ST Service see the [:blue_book: **full documenation**](https://faaast-service.readthedocs.io/).
> For more details on FA³ST Service see the [:blue_book: **full documentation**](https://faaast-service.readthedocs.io/).


## Implemented AAS Specifications

- AAS Part 1: Metamodel v3.0 [Specification](https://industrialdigitaltwin.org/wp-content/uploads/2023/06/IDTA-01001-3-0_SpecificationAssetAdministrationShell_Part1_Metamodel.pdf)
- AAS Part 2: API v3.0.1 [Specification](https://industrialdigitaltwin.org/wp-content/uploads/2023/06/IDTA-01002-3-0_SpecificationAssetAdministrationShell_Part2_API_.pdf), [OpenAPI](https://app.swaggerhub.com/apis/Plattform_i40/Entire-API-Collection/V3.0.1)
- AAS Part 3a: Data Specification – IEC 61360 v3.0 [Specification](https://industrialdigitaltwin.org/en/wp-content/uploads/sites/2/2024/07/IDTA-01003-a-3-0-2_SpecificationAssetAdministrationShell_Part3a_DataSpecification_IEC613601.pdf)
- AAS Part 5: Package File Format (AASX) v3.0 [Specification](https://industrialdigitaltwin.org/en/wp-content/uploads/sites/2/2024/06/IDTA-01005-3-0-1_SpecificationAssetAdministrationShell_Part5_AASXPackageFileFormat.pdf)
- AAS Part 1: Metamodel v3.1.2 [Specification](https://industrialdigitaltwin.org/wp-content/uploads/2025/11/IDTA-01001-3-1-2_AAS-Specification_Part1_Metamodel.pdf)
- AAS Part 2: API v3.1.2 [Specification](https://industrialdigitaltwin.org/wp-content/uploads/2026/04/IDTA-01002-3-1-2_AAS-Specification_Part2_API.pdf), [OpenAPI](https://app.swaggerhub.com/apis/Plattform_i40/Entire-API-Collection/V3.1.2)
- AAS Part 3a: Data Specification – IEC 61360 v3.1.1 [Specification](https://industrialdigitaltwin.org/wp-content/uploads/2025/08/IDTA-01003-a-3-1-1_AAS-Specification_Part3a_DataSpecification.pdf)
- AAS Part 5: Package File Format (AASX) v3.1 [Specification](https://industrialdigitaltwin.org/wp-content/uploads/2025/06/IDTA_01005-25-01_AAS-Specification_Part5_AASXPackageFileFormat.pdf)


## Usage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
import org.apache.commons.lang3.tuple.Pair;
import org.eclipse.digitaltwin.aas4j.v3.model.DataElement;
import org.eclipse.digitaltwin.aas4j.v3.model.KeyTypes;
import org.eclipse.digitaltwin.aas4j.v3.model.MessageTypeEnum;
import org.eclipse.digitaltwin.aas4j.v3.model.MessageType;
import org.eclipse.digitaltwin.aas4j.v3.model.OperationVariable;
import org.eclipse.digitaltwin.aas4j.v3.model.Reference;
import org.eclipse.digitaltwin.aas4j.v3.model.SubmodelElement;
Expand Down Expand Up @@ -110,7 +110,7 @@ List<AssetConnection> getConnections() {
*/
public void cleanupDanglingConnectionsAfterModify(Reference modifiedElement) {
Predicate<Reference> condition = x -> ReferenceHelper.startsWith(x, modifiedElement) && !service.getPersistence().submodelElementExists(x);
connections.stream()
connections
.forEach(LambdaExceptionHelper.rethrowConsumer(connection -> {
for (var providerType: AssetProviderType.values()) {
providerType.getProvidersFromConnectionAccessor().apply(connection).keySet().stream()
Expand Down Expand Up @@ -169,7 +169,7 @@ public List<Message> updateConnections(List<AssetConnectionConfig> oldConfigs, L
}
catch (ConfigurationException e) {
return List.of(Message.builder()
.messageType(MessageTypeEnum.EXCEPTION)
.messageType(MessageType.EXCEPTION)
.text(e.getMessage())
.build());
}
Expand Down Expand Up @@ -360,8 +360,7 @@ public void syncValueProvidersOnWrite(Reference reference, Object oldElement, Ob
else {
Map<Reference, DataElement> oldChildren = findSynchronizableElements(reference, oldElement);
Map<Reference, DataElement> newChildren = findSynchronizableElements(reference, newElement);
newChildren.entrySet().stream()
.forEach(x -> syncElementOnWrite(x.getKey(), Pair.of(oldChildren.get(x.getKey()), x.getValue()), publishOnMessageBus));
newChildren.forEach((key, value) -> syncElementOnWrite(key, Pair.of(oldChildren.get(key), value), publishOnMessageBus));
}
}

Expand Down Expand Up @@ -728,7 +727,7 @@ private List<Message> apply(List<AssetConnectionConfig> newConnections) {
}
catch (ConfigurationException e) {
result.add(Message.builder()
.messageType(MessageTypeEnum.EXCEPTION)
.messageType(MessageType.EXCEPTION)
.text(String.format("Adding asset connection failed (reason: %s)",
e.getMessage()))
.build());
Expand Down Expand Up @@ -796,12 +795,12 @@ private List<AssetConnectionConfig> mergeChanges(List<AssetConnection> currentCo
}
else {
messages.add(Message.builder()
.messageType(MessageTypeEnum.INFO)
.messageType(MessageType.INFO)
.text("Deleting asset connection skipped (reason: connection does not exist)")
.build());
}
}
if (messages.stream().anyMatch(x -> x.getMessageType() == MessageTypeEnum.ERROR || x.getMessageType() == MessageTypeEnum.EXCEPTION)) {
if (messages.stream().anyMatch(x -> x.getMessageType() == MessageType.ERROR || x.getMessageType() == MessageType.EXCEPTION)) {
throw new ExceptionWithDetails("failed to apply changes in asset connections", messages);
}
return result;
Expand All @@ -819,7 +818,7 @@ private List<Message> deleteProviders(AssetConnectionConfig target, AssetConnect
}
else {
result.add(Message.builder()
.messageType(MessageTypeEnum.WARNING)
.messageType(MessageType.WARNING)
.text(String.format(
"Failed to unregister %s provider (reference: %s, reason: existing provider details for reference differs from expected provider)",
providerType.toString().toLowerCase(),
Expand All @@ -829,7 +828,7 @@ private List<Message> deleteProviders(AssetConnectionConfig target, AssetConnect
}
else {
result.add(Message.builder()
.messageType(MessageTypeEnum.INFO)
.messageType(MessageType.INFO)
.text(String.format("Failed to unregister %s provider (reference: %s, reason: provider does not exist)",
providerType.toString().toLowerCase(),
ReferenceHelper.asString(reference)))
Expand Down Expand Up @@ -861,7 +860,7 @@ private List<Message> addProvidersToConnection(AssetConnection target, AssetConn
}
catch (AssetConnectionException e) {
result.add(Message.builder()
.messageType(MessageTypeEnum.WARNING)
.messageType(MessageType.WARNING)
.text(String.format("Failed to unsubscribe subscription (reference: %s, reason: %s)",
ReferenceHelper.asString(reference),
e.getMessage()))
Expand All @@ -881,7 +880,7 @@ private List<Message> addProvidersToConnection(AssetConnection target, AssetConn
}
catch (AssetConnectionException e) {
result.add(Message.builder()
.messageType(MessageTypeEnum.EXCEPTION)
.messageType(MessageType.EXCEPTION)
.text(String.format("Failed to register %s provider (reference: %s, reason: %s)",
providerType.toString().toLowerCase(),
ReferenceHelper.asString(reference),
Expand All @@ -899,7 +898,7 @@ private List<Message> addProvidersToConnection(AssetConnection target, AssetConn
}
catch (AssetConnectionException e) {
result.add(Message.builder()
.messageType(MessageTypeEnum.EXCEPTION)
.messageType(MessageType.EXCEPTION)
.text(String.format("Failed to unregister %s provider (reference: %s, reason: %s)",
providerType.toString().toLowerCase(),
ReferenceHelper.asString(reference),
Expand All @@ -921,7 +920,7 @@ private List<Message> addProviders(AssetConnectionConfig target, AssetConnection
if (Objects.nonNull(reference)
&& provider.getValue().equals(providerType.getProvidersFromConfigAccessor().apply(target).get(reference))) {
result.add(Message.builder()
.messageType(MessageTypeEnum.INFO)
.messageType(MessageType.INFO)
.text(String.format("Skipped adding %s provider (reference: %s, reason: already exists)",
providerType.toString().toLowerCase(),
ReferenceHelper.asString(reference)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ private SubmodelDescriptor asDescriptor(Submodel submodel) {
.idShort(submodel.getIdShort())
.description(submodel.getDescription())
.semanticId(submodel.getSemanticId())
.supplementalSemanticId(submodel.getSupplementalSemanticIds())
.supplementalSemanticIds(submodel.getSupplementalSemanticIds())
.displayName(submodel.getDisplayName())
.extensions(submodel.getExtensions())
.endpoints(endpoints.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
import java.util.stream.Collectors;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.apache.commons.lang3.reflect.ConstructorUtils;
import org.eclipse.digitaltwin.aas4j.v3.model.MessageTypeEnum;
import org.eclipse.digitaltwin.aas4j.v3.model.MessageType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -135,29 +135,29 @@ public <I extends Request<O>, O extends Response> O execute(I request, RequestEx
throw new IllegalArgumentException("request must be non-null");
}
if (!handlers.containsKey(request.getClass())) {
return createResponse(request, StatusCode.SERVER_INTERNAL_ERROR, MessageTypeEnum.EXCEPTION, "no handler defined for this request");
return createResponse(request, StatusCode.SERVER_INTERNAL_ERROR, MessageType.EXCEPTION, "no handler defined for this request");
}
try {
return (O) handlers.get(request.getClass()).process(request, context);
}
catch (ResourceNotFoundException e) {
return createResponse(request, StatusCode.CLIENT_ERROR_RESOURCE_NOT_FOUND, MessageTypeEnum.ERROR, e);
return createResponse(request, StatusCode.CLIENT_ERROR_RESOURCE_NOT_FOUND, MessageType.ERROR, e);
}
catch (ResourceAlreadyExistsException e) {
return createResponse(request, StatusCode.CLIENT_RESOURCE_CONFLICT, MessageTypeEnum.ERROR, e);
return createResponse(request, StatusCode.CLIENT_RESOURCE_CONFLICT, MessageType.ERROR, e);
}
catch (ValidationException e) {
return createResponse(request, StatusCode.CLIENT_ERROR_BAD_REQUEST, MessageTypeEnum.ERROR, e);
return createResponse(request, StatusCode.CLIENT_ERROR_BAD_REQUEST, MessageType.ERROR, e);
}
}


private static <I extends Request<O>, O extends Response> O createResponse(I request, StatusCode statusCode, MessageTypeEnum messageType, Exception e) {
private static <I extends Request<O>, O extends Response> O createResponse(I request, StatusCode statusCode, MessageType messageType, Exception e) {
return createResponse(request, statusCode, messageType, e.getMessage());
}


private static <I extends Request<O>, O extends Response> O createResponse(I request, StatusCode statusCode, MessageTypeEnum messageType, String message) {
private static <I extends Request<O>, O extends Response> O createResponse(I request, StatusCode statusCode, MessageType messageType, String message) {
try {
O response = (O) ConstructorUtils.invokeConstructor(TypeToken.of(request.getClass()).resolveType(Request.class.getTypeParameters()[0]).getRawType());
response.setStatusCode(statusCode);
Expand Down Expand Up @@ -196,7 +196,7 @@ public <I extends Request<O>, O extends Response> void executeAsync(I request, C
}
catch (Exception e) {
LOGGER.trace("Error while executing request", e);
callback.accept(createResponse(request, StatusCode.SERVER_INTERNAL_ERROR, MessageTypeEnum.EXCEPTION, e));
callback.accept(createResponse(request, StatusCode.SERVER_INTERNAL_ERROR, MessageType.EXCEPTION, e));
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,16 @@


/**
* Not supported yet! Class to handle a
* {@link de.fraunhofer.iosb.ilt.faaast.service.model.api.request.aasbasicdiscovery.GetAllAssetAdministrationShellIdsByAssetLinkRequest}
* in the service and to send the corresponding response
* {@link de.fraunhofer.iosb.ilt.faaast.service.model.api.response.aasbasicdiscovery.GetAllAssetAdministrationShellIdsByAssetLinkResponse}.
* Is responsible for communication with the persistence and sends the corresponding events to the message bus.
* Class to handle a {@link GetAllAssetAdministrationShellIdsByAssetLinkRequest} in the service and to send the
* corresponding response
* {@link GetAllAssetAdministrationShellIdsByAssetLinkResponse}. Is responsible for communication with the persistence
* and sends the corresponding events to the message bus.
*
* @deprecated GetAllAssetAdministrationShellIdsByAssetLinkRequest was replaced by
* SearchAllAssetAdministrationShellIdsByAssetLinkRequest from AAS API v3.1
*/
@Deprecated(since = "1.4")
public class GetAllAssetAdministrationShellIdsByAssetLinkRequestHandler

Check warning on line 41 in core/src/main/java/de/fraunhofer/iosb/ilt/faaast/service/request/handler/aasbasicdiscovery/GetAllAssetAdministrationShellIdsByAssetLinkRequestHandler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Do not forget to remove this deprecated code someday.

See more on https://sonarcloud.io/project/issues?id=FraunhoferIOSB_FAAAST-Service&issues=AZ6mGV0utL-uikdzjhuN&open=AZ6mGV0utL-uikdzjhuN&pullRequest=1413
extends AbstractRequestHandler<GetAllAssetAdministrationShellIdsByAssetLinkRequest, GetAllAssetAdministrationShellIdsByAssetLinkResponse> {

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2021 Fraunhofer IOSB, eine rechtlich nicht selbstaendige
* Einrichtung der Fraunhofer-Gesellschaft zur Foerderung der angewandten
* Forschung e.V.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.fraunhofer.iosb.ilt.faaast.service.request.handler.aasbasicdiscovery;

import de.fraunhofer.iosb.ilt.faaast.service.model.api.modifier.QueryModifier;
import de.fraunhofer.iosb.ilt.faaast.service.model.api.paging.Page;
import de.fraunhofer.iosb.ilt.faaast.service.model.api.request.aasbasicdiscovery.SearchAllAssetAdministrationShellIdsByAssetLinkRequest;
import de.fraunhofer.iosb.ilt.faaast.service.model.api.response.aasbasicdiscovery.SearchAllAssetAdministrationShellIdsByAssetLinkResponse;
import de.fraunhofer.iosb.ilt.faaast.service.model.exception.PersistenceException;
import de.fraunhofer.iosb.ilt.faaast.service.persistence.AssetAdministrationShellSearchCriteria;
import de.fraunhofer.iosb.ilt.faaast.service.request.handler.AbstractRequestHandler;
import de.fraunhofer.iosb.ilt.faaast.service.request.handler.RequestExecutionContext;
import java.util.List;
import org.eclipse.digitaltwin.aas4j.v3.model.AssetAdministrationShell;
import org.eclipse.digitaltwin.aas4j.v3.model.Identifiable;


/**
* Class to handle a
* {@link SearchAllAssetAdministrationShellIdsByAssetLinkRequest}
* in the service and to send the corresponding response
* {@link SearchAllAssetAdministrationShellIdsByAssetLinkResponse}.
* Is responsible for communication with the persistence and sends the corresponding events to the message bus.
*/
public class SearchAllAssetAdministrationShellIdsByAssetLinkRequestHandler
extends AbstractRequestHandler<SearchAllAssetAdministrationShellIdsByAssetLinkRequest, SearchAllAssetAdministrationShellIdsByAssetLinkResponse> {

@Override
public SearchAllAssetAdministrationShellIdsByAssetLinkResponse process(SearchAllAssetAdministrationShellIdsByAssetLinkRequest request, RequestExecutionContext context)
throws PersistenceException {
Page<AssetAdministrationShell> aass = context.getPersistence().findAssetAdministrationShells(
AssetAdministrationShellSearchCriteria.builder()
.assetIds(parseSpecificAssetIds(request.getAssetIdentifierPairs()))
.build(),
QueryModifier.DEFAULT,
request.getPagingInfo());

List<String> result = aass.getContent()
.stream()
.map(Identifiable::getId)
.toList();
return SearchAllAssetAdministrationShellIdsByAssetLinkResponse.builder()
.payload(Page.<String> builder()
.metadata(aass.getMetadata())
.result(result)
.build())
.success()
.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import de.fraunhofer.iosb.ilt.faaast.service.util.ReferenceHelper;
import de.fraunhofer.iosb.ilt.faaast.service.util.ResponseHelper;
import java.util.List;
import org.eclipse.digitaltwin.aas4j.v3.model.MessageTypeEnum;
import org.eclipse.digitaltwin.aas4j.v3.model.MessageType;
import org.eclipse.digitaltwin.aas4j.v3.model.Operation;
import org.eclipse.digitaltwin.aas4j.v3.model.Reference;

Expand Down Expand Up @@ -61,7 +61,7 @@ protected DeleteOperationProviderByPathResponse doProcess(DeleteOperationProvide

AssetConnectionConfig<?, ?, ?, ?> config = OperationProviderHelper.convertBodyToAssetConnectionConfig(request.getBody(), reference);
List<Message> result = context.getAssetConnectionManager().updateConnections(List.of(config), List.of()).stream()
.filter(x -> x.getMessageType() == MessageTypeEnum.ERROR || x.getMessageType() == MessageTypeEnum.EXCEPTION)
.filter(x -> x.getMessageType() == MessageType.ERROR || x.getMessageType() == MessageType.EXCEPTION)
.toList();
LogHelper.logMessages(result);
return DeleteOperationProviderByPathResponse.builder()
Expand Down
Loading