• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

FIWARE / contract-management / #105

01 Oct 2026 08:22AM UTC coverage: 4.489% (+0.7%) from 3.796%
#105

push

web-flow
Merge pull request #28 from FIWARE/topic/clearer-logging

Add failure reasons, downstream error descriptions and configurable log output

218 of 379 new or added lines in 33 files covered. (57.52%)

9 existing lines in 6 files now uncovered.

1606 of 35773 relevant lines covered (4.49%)

0.04 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

58.0
/src/main/java/org/fiware/iam/tmforum/OrganizationResolver.java
1
package org.fiware.iam.tmforum;
2

3
import com.fasterxml.jackson.databind.ObjectMapper;
4
import io.micronaut.context.annotation.Requires;
5
import io.micronaut.context.annotation.Value;
6
import jakarta.inject.Singleton;
7
import lombok.RequiredArgsConstructor;
8
import lombok.extern.slf4j.Slf4j;
9
import org.fiware.iam.configuration.GeneralProperties;
10
import org.fiware.iam.domain.ContractManagement;
11
import io.micronaut.http.client.exceptions.HttpClientResponseException;
12
import org.fiware.iam.exception.FailureReason;
13
import org.fiware.iam.exception.TMForumException;
14
import org.fiware.iam.tmforum.party.api.OrganizationApiClient;
15
import org.fiware.iam.tmforum.party.model.CharacteristicVO;
16
import org.fiware.iam.tmforum.party.model.ExternalReferenceVO;
17
import org.fiware.iam.tmforum.party.model.OrganizationVO;
18
import reactor.core.publisher.Mono;
19

20
import java.util.List;
21
import java.util.Optional;
22

23
@Requires(condition = GeneralProperties.TmForumCondition.class)
24
@Singleton
25
@Slf4j
1 ✔
26
@RequiredArgsConstructor
27
public class OrganizationResolver {
28

29
    @Value("${general.organization.provider.role:provider}")
30
    private String PROVIDER_ROLE;
31

32
    private static final String PARTY_CHARACTERISTIC_DID = "did";
33
    private static final String FIELD_NAME_CONTRACT_MANAGEMENT = "contractManagement";
34
    private static final String EXTERNAL_REFERENCE_IDM_ID = "idm_id";
35
    private static final String DID = "did";
36

37
    private final GeneralProperties generalProperties;
38
    private final ObjectMapper objectMapper;
39
    private final OrganizationApiClient apiClient;
40

41
    //TODO Cache me if you can
42
    public Mono<String> getDID(String organizationId) {
43
        return retrieveOrganization(organizationId)
1 ✔
44
                .map(ovo -> getDid(organizationId, ovo));
1 ✔
45
    }
46

47
    public Mono<ContractManagement> getContractManagement(String organizationId) {
NEW
48
        return retrieveOrganization(organizationId)
×
NEW
49
                .map(ovo -> {
×
NEW
50
                    if (getDid(organizationId, ovo).equals(generalProperties.getDid())) {
×
NEW
51
                        return new ContractManagement(true);
×
52
                    }
NEW
53
                    return Optional.ofNullable(ovo.getPartyCharacteristic())
×
NEW
54
                            .orElse(List.of())
×
NEW
55
                            .stream()
×
NEW
56
                            .filter(pc -> FIELD_NAME_CONTRACT_MANAGEMENT.equals(pc.getName()))
×
NEW
57
                            .map(CharacteristicVO::getValue)
×
NEW
58
                            .map(pcv -> objectMapper.convertValue(pcv, ContractManagement.class))
×
NEW
59
                            .findAny()
×
NEW
60
                            .orElse(new ContractManagement(true));
×
61
                });
62
    }
63

64
    private Mono<OrganizationVO> retrieveOrganization(String organizationId) {
65
        return apiClient.retrieveOrganization(organizationId, null)
1 ✔
66
                .onErrorMap(HttpClientResponseException.class, e -> new TMForumException(FailureReason.ORGANIZATION_NOT_FOUND,
1 ✔
67
                        "Organization %s could not be retrieved from the TM Forum party API.".formatted(organizationId), e))
1 ✔
68
                .map(response -> {
1 ✔
69
                    if (response.body() == null) {
1 ✔
70
                        throw new TMForumException(FailureReason.ORGANIZATION_NOT_FOUND,
1 ✔
71
                                "Organization %s could not be retrieved from the TM Forum party API, the answer has no body.".formatted(organizationId));
1 ✔
72
                    }
73
                    return response.body();
1 ✔
74
                })
75
                .switchIfEmpty(Mono.error(() -> new TMForumException(FailureReason.ORGANIZATION_NOT_FOUND,
1 ✔
NEW
76
                        "Organization %s could not be retrieved from the TM Forum party API, the response was empty.".formatted(organizationId))));
×
77
    }
78

79
    private String getDid(String organizationId, OrganizationVO ovo) {
80
        String did = getDidFromExternalReference(ovo.getExternalReference())
1 ✔
81
                .or(() -> getDidFromPartyCharacteristics(ovo.getPartyCharacteristic()))
1 ✔
82
                .orElseThrow(() -> new TMForumException(FailureReason.ORGANIZATION_DID_MISSING,
1 ✔
83
                        "Organization %s has no valid DID in an externalReference of type '%s' or a partyCharacteristic '%s'.".formatted(
1 ✔
84
                                organizationId, EXTERNAL_REFERENCE_IDM_ID, PARTY_CHARACTERISTIC_DID)));
85
        log.debug("Organization {} has DID {}", organizationId, did);
1 ✔
86
        return did;
1 ✔
87
    }
88

89
    public boolean hasProviderRole(String role) {
90
        return PROVIDER_ROLE.equalsIgnoreCase(role);
×
91
    }
92

93
    private Optional<String> getDidFromPartyCharacteristics(List<CharacteristicVO> characteristicVOS) {
94
        if (characteristicVOS == null) {
1 ✔
95
            return Optional.empty();
1 ✔
96
        }
97
        return characteristicVOS.stream()
×
98
                .filter(entry -> PARTY_CHARACTERISTIC_DID.equals(entry.getName()))
×
99
                .map(CharacteristicVO::getValue)
×
100
                .filter(e -> e instanceof String)
×
101
                .map(e -> (String) e)
×
102
                .filter(this::isDid)
×
103
                .findAny();
×
104
    }
105

106
    private Optional<String> getDidFromExternalReference(List<ExternalReferenceVO> externalReferenceVOList) {
107
        if (externalReferenceVOList == null) {
1 ✔
108
            return Optional.empty();
1 ✔
109
        }
110
        return externalReferenceVOList.stream()
1 ✔
111
                .filter(ervo -> EXTERNAL_REFERENCE_IDM_ID.equals(ervo.getExternalReferenceType()))
1 ✔
112
                .map(ExternalReferenceVO::getName)
1 ✔
113
                .filter(this::isDid)
1 ✔
114
                .findFirst();
1 ✔
115
    }
116

117
    private boolean isDid(String id) {
118
        String[] idParts = id.split(":");
1 ✔
119
        return idParts.length >= 3 && idParts[0].equals(DID);
1 ✔
120
    }
121
}
122

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc